mysqlsqljsonwhere-clausehaving-clause

Using multiple HAVING clause on SQL statement using JSON_EXTRACT


I am using MYSQL 6.x with JSON functions and have the following query that I am trying to use WHERE or HAVING to limit the recordset - there is a column called properties which is JSON column and I need to perform a search with multiple conditions on this json data

SELECT JSON_EXTRACT(properties,'$.identifier') AS identifier,
       JSON_EXTRACT(properties,'$.workflow_type') AS workflow_type
       FROM workflow_pages HAVING workflow_type;

This returns the following data :-

+------------+---------------+
| identifier | workflow_type |
+------------+---------------+
| 9          | "dictionary"  |
| 13         | "dictionary"  |
| 11         | "dictionary"  |
| 13         | "rule"        |
| 134        | "rule"        |
+------------+---------------+

How do I perform the same query above to only return the rows which have the following conditions identifier IN 13, 134 AND workflow_type = 'rule'

How do I amend my query to do this as it seems MySQL doesn't allow for multiple HAVING conditions


Solution

  • You sure can have multiple conditions in the HAVING clause (as opposed to multiple HAVING clauses):

    SELECT 
        JSON_EXTRACT(properties,'$.identifier') AS identifier,
        JSON_EXTRACT(properties,'$.workflow_type') AS workflow_type
    FROM workflow_pages 
    HAVING workflow_type = 'rule' AND identifier IN (13, 134)
    

    But I would not actually recommend phrasing the query this way; you are relying on MySQL's extension to the SQL standard which allows aliases in the HAVING clause (and without a GROUP BY), and it makes the query quite unclear in some regard. I find that it is much better to use a regular WHERE clause and repeat the expressions:

    SELECT 
        JSON_EXTRACT(properties,'$.identifier') AS identifier,
        JSON_EXTRACT(properties,'$.workflow_type') AS workflow_type
    FROM workflow_pages 
    WHERE 
        JSON_EXTRACT(properties,'$.identifier') IN (12, 134)
        JSON_EXTRACT(properties,'$.workflow_type') = 'rule'
    

    Or if you have a lot of conditions and don't want to do all the typing, you can use a subquery (I would expect MySQL to do predicate pushdown and optimize it for you under the hood):

    SELECT *
    FROM (
        SELECT 
            JSON_EXTRACT(properties,'$.identifier') AS identifier,
            JSON_EXTRACT(properties,'$.workflow_type') AS workflow_type
        FROM workflow_pages 
    ) t
    WHERE workflow_type = 'rule' AND identifier IN (13, 134)