Search code examples
sqlclickhouse

Combine few same SELECT queries into one with set of "where"-data


My query is simple, like:

SELECT * 
FROM abc.def
WHERE a = 'some_a_value' AND b = 'some_b_value';

But I need get data for collection of "input values", like this:

SELECT * 
FROM abc.def
WHERE
    (a = 'some_a_value' AND b = 'some_b_value')
    OR (a = 'another_a_value' AND b = 'another_b_value')
    OR ___etc.___

And also I need to now which result is for which source data. it's pretty easy to do it in PostgreSQL:

WITH src AS 
(
    SELECT * 
    FROM 
        (VALUES (1, 'hello', 'world'),
                (2, 'test', 'data'),
                (3, 'more', 'data')) as bla_bla(num, text_a, text_b)
)
SELECT s.num, t.a, t.b, t.useful_data
FROM my_table AS t
JOIN src AS s ON (t.a = s.text_a AND t.b = s.text_b);

But Clickhouse doesn't allow using VALUES inside WITH.
At the moment I've found only one solution:

WITH src AS 
(
    SELECT 1 AS num, 'some_a_data' AS a, 'some_b_data' AS b
    UNION ALL 
    SELECT 2 AS num, 'another_a_data' AS a, 'another_b_data' AS b
    UNION ALL __&_etc.__
)
SELECT __&_etc.__

Is it correct or only way?


Solution

  • Finally I've found solution by myself. Clickhouse allows to use VALUES inside WITH, but unlike Postgres, VALUES should not be covered by braces

    WITH src AS (
        SELECT * FROM VALUES (
            'num int, msg String',
            (1, 'hello'),
            (2, 'world'),
            (3, '!')
        )
    )
    SELECT * FROM src;
    
    -- Results:
    -- num|msg  |
    -- ---+-----+
    --   1|hello|
    --   2|world|
    --   3|!    |
    

    But user needs extra privileges to do it: SQL Error [497] [07000]: Code: 497. DB::Exception: mike_pryadko: Not enough privileges. To execute this query it's necessary to have grant CREATE TEMPORARY TABLE ON *.*. (ACCESS_DENIED)

    Another way - array of tuples:

    WITH [
        ('hello', 'world', 'en'),
        ('hola', 'mundo', 'es'),
        ('привет', 'мир', 'ru')
    ] AS src
    SELECT a, b, lang
    FROM (SELECT null)
    ARRAY JOIN
        arrayMap(src -> src.1, src) AS a,
        arrayMap(src -> src.2, src) AS b,
        arrayMap(src -> src.3, src) AS lang,
        arrayEnumerate(src) AS idx;
    
    -- Result:
    -- a     |b    |lang|
    -- ------+-----+----+
    -- hello |world|en  |
    -- hola  |mundo|es  |
    -- привет|мир  |ru  |