简体   繁体   中英

Use result of 'IF' in 'SELECT' in 'WHERE' clause in SQL query

We have the following query:

SELECT
        foo_id,
        IF (( SELECT
            COUNT(foo_mapping_id) 
        FROM
            foo_bar_mappings,
            bar
        WHERE
            foo_mapping_foo_id = foo_id
            AND foo_mapping_bar_id = bar_id ) > 0,
        foo_status,
        'inactive') AS foo_status
    FROM
        foo
    WHERE
        foo_status = 'inactive'

When we run it, we get an empty result, because foo_status is not equal to inactive (while there are rows that satisfy the IF ). foo_status is a column that exists in the foo table, but we want to "overwrite" it.

How would we change this query so we can use the foo_status as returned by the IF in our WHERE clause? Obviously this query has been simplified to make the question easier to ask and understand.

You cannot use a column alias in a where clause. MySQL does extend the HAVING clause so it can be used instead:

having foo_status = 'inactive'

Note:

I would write the query as:

SELECT f.foo_id,
       (CASE WHEN (EXISTS (SELECT 1
                           FROM foo_bar_mappings fb JOIN
                                bar b
                                ON fb.foo_mapping_bar_id = b.bar_id
                           WHERE fb.foo_mapping_foo_id = f.foo_id
                          ) 
             THEN foo_status
             ELSE 'inactive'
         END) AS new_foo_status
FROM foo f
HAVING new_foo_status = 'inactive';

Notes:

  • EXISTS is more efficient than COUNT(*) in this context.
  • I prefer CASE to IF() because the former is ANSI standard.
  • I am uncomfortable using a column alias that has the same name as a real column. This can be confusing when the alias is used.

As already suggested in other answer you can use the column alias in HAVING clause but I see you have no GROUP BY in your posted query. In such case, you can use the aliased column in a outer query like

SELECT * FROM (
SELECT
        foo_id,
        IF (( SELECT
            COUNT(foo_mapping_id) 
        FROM
            foo_bar_mappings,
            bar
        WHERE
            foo_mapping_foo_id = foo_id
            AND foo_mapping_bar_id = bar_id ) > 0,
        foo_status,
        'inactive') AS foo_status
    FROM
        foo ) xxx
    WHERE
        foo_status = 'inactive'

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM