2017-10-30 6 views
0

特定のpkeyを持つ一意のユーザー数とそのpkeyを持たない一意のユーザーの数をカウントする方法を探しています。ここでImpalaクエリ - クエリを最適化して特定のキーのユニークを取得する

は、サンプルテーブルです:

userid | pkey  | pvalue 
------------------------------ 
    U1 | x  | vx 
    U1 | y  | vy 
    U1 | z  | vz 
    U2 | y  | vy 
    U3 | z  | vz 
    U4 | null  | null 

私が期待される結果がPKEY =「Y」を持っているし、このクエリを使用したが、高価であることが判明しなかった人ユニークユーザーを取得するには、Get :

WITH all_rows AS 
    (SELECT userid, 
      IF(pkey='y', pval, 'none') AS val, 
      SUM(IF(pkey='y',1,0)) AS has_key 
    FROM some_table 
    GROUP BY userid, val) 
SELECT val, 
     count(distinct(userid)) uniqs 
FROM all_rows 
WHERE has_key=1 
GROUP BY val 
UNION ALL 
SELECT 'no_key_set' val, 
     count(distinct(userid)) uniqs 
FROM all_rows a1 LEFT ANTI JOIN 
    all_rows a2 on (a1.userid = a2.userid and a2.has_key=1) 
GROUP BY val; 

Results: 

val  | uniqs 
-------------------- 
vy   | 2 
no_key_set | 2 

一時テーブルを使用しないようにしたいので、これを実現する方法はありますか?

ありがとうございます!

答えて

0

EXPLAINを使用すると、元のクエリでサブクエリを使用するのではなく、大量のGROUP BY集計を実行するのに費やされることがわかります。ここで

WITH t1 AS (
    SELECT pkey, COUNT(*) AS cnt 
    FROM table 
    WHERE pkey IS NOT NULL 
    GROUP BY pkey 
), t2 AS (
    SELECT COUNT(DISTINCT userid) AS total_cnt 
    FROM table 
) 
SELECT 
    CONCAT('no_', pkey) AS pkey, 
    (total_cnt - cnt) AS cnt 
FROM t1, t2 
UNION ALL 
SELECT * FROM t1 
  • t1

    +------+-----+ 
    | pkey | cnt | 
    +------+-----+ 
    | x | 1 | 
    | z | 2 | 
    | y | 2 | 
    +------+-----+ 
    
  • t2が総ユニークユーザーの数を取得しますPKEYあたりのユニークユーザー数のテーブルを取得する簡単な実装です

    +-----------+ 
    | total_cnt | 
    +-----------+ 
    | 4   | 
    +-----------+ 
    
  • 我々は二つのテーブルの最後の労働組合が

    +------+-----+ 
    | pkey | cnt | 
    +------+-----+ 
    | no_x | 3 | 
    | no_z | 2 | 
    | no_y | 2 | 
    | x | 1 | 
    | z | 2 | 
    | y | 2 | 
    +------+-----+ 
    
の結果を与える t1

+------+-----+ 
| pkey | cnt | 
+------+-----+ 
| no_x | 3 | 
| no_z | 2 | 
| no_y | 2 | 
+------+-----+ 
  • の補数テーブルを取得するためにt2からの結果を使用することができます