2017-08-21 3 views
0

gibt es eine Möglichkeit, die Gesamtzahl der Zeilen pro {ID, Datum} und die Anzahl> 1 pro {ID, Datum, SpalteX} in derselben Abfrage zu erhalten?Anzahl und Anzahl in der gleichen Abfrage

Zum Beispiel kann eine solche Tabelle:

id   date   columnX 
1  2017-04-20   a 
1  2017-04-20   a 
1  2017-04-18   b 
1  2017-04-17   c 
2  2017-04-20   a 
2  2017-04-20   a 
2  2017-04-20   c 
2  2017-04-19   b 
2  2017-04-19   b 
2  2017-04-19   b 
2  2017-04-19   b 
2  2017-04-19   c 

Als Ergebnis, möchte ich die folgende Tabelle erhalten:

id   date  columnX   count>1 count_total 
1  2017-04-20  a    2   2 
2  2017-04-20  a    2   3 
2  2017-04-19  b    4   5 

Ich habe versucht, indem sie sie mit Partition zu tun, aber seltsame Ergebnisse erhalten. Ich habe gehört, Rollup-Funktion könnte verwendet werden, aber es scheint, dass es nur in Legacy-SQL anwendbar ist, die nicht die Option für mich ist.

Antwort

2

Wenn ich richtig verstehe, können Sie Fensterfunktionen verwenden:

select id, date, columnx, cnt, 
     (case when cnt > 1 then cnt else 0 end) as cnt_gt_1, 
     total_cnt 
from (select id, date, columnx, count(*) as cnt 
      sum(count(*)) over (partition by id, date) as total_cnt 
     from t 
     group by id, date, columnx 
    ) x 
where cnt > 1; 
+0

Vielen Dank! Löst das Problem. Allerdings musste eine weitere Abfrage hinzugefügt werden (wählen Sie * aus Ihrer Abfrage, wo cnt> 1), da 'where cnt> 1' in Ihrer Abfrage auch diese aus dem Total entfernte. – hamsy

1

Eine andere Möglichkeit:

SELECT 
    id, 
    date, 
    data.columnX columnX, 
    data.count_ count_bigger_1, 
    count_total 
FROM(
    SELECT 
    id, 
    date, 
    ARRAY_AGG(columnX) data, 
    COUNT(1) count_total 
    FROM 
    `your_table_name` 
    GROUP BY 
    id, date 
), 
UNNEST(ARRAY(SELECT AS STRUCT columnX, count(1) count_ FROM UNNEST(data) columnX GROUP BY columnX HAVING count(1) > 1)) data 

Sie es mit simulierten Daten testen können:

WITH data AS(
    SELECT 1 AS id, '2017-04-20' AS date, 'a' AS columnX UNION ALL 
    SELECT 1 AS id, '2017-04-20' AS date, 'a' AS columnX UNION ALL 
    SELECT 1 AS id, '2017-04-18' AS date, 'b' AS columnX UNION ALL 
    SELECT 1 AS id, '2017-04-17' AS date, 'c' AS columnX UNION ALL 
    SELECT 2 AS id, '2017-04-20' AS date, 'a' AS columnX UNION ALL 
    SELECT 2 AS id, '2017-04-20' AS date, 'a' AS columnX UNION ALL 
    SELECT 2 AS id, '2017-04-20' AS date, 'c' AS columnX UNION ALL 
    SELECT 2 AS id, '2017-04-19' AS date, 'b' AS columnX UNION ALL 
    SELECT 2 AS id, '2017-04-19' AS date, 'b' AS columnX UNION ALL 
    SELECT 2 AS id, '2017-04-19' AS date, 'b' AS columnX UNION ALL 
    SELECT 2 AS id, '2017-04-19' AS date, 'b' AS columnX UNION ALL 
    SELECT 2 AS id, '2017-04-19' AS date, 'c' AS columnX 
) 

SELECT 
    id, 
    date, 
    data.columnX columnX, 
    data.count_ count_bigger_1, 
    count_total 
FROM(
    SELECT 
    id, 
    date, 
    ARRAY_AGG(columnX) data, 
    COUNT(1) count_total 
    FROM 
    data 
    GROUP BY 
    id, date 
), 
UNNEST(ARRAY(SELECT AS STRUCT columnX, count(1) count_ FROM UNNEST(data) columnX GROUP BY columnX HAVING count(1) > 1)) data 

Durch diese Lösung wird die analytische Funktion (die je nach Eingabe sehr teuer sein kann) und skaliert gut zu großen vol Daten.

1

Ich empfehle Ihnen, in Ihrem Beispiel fügen zwei weitere unter Reihen

1  2017-04-20   x 
1  2017-04-20   x 

und prüfen, welche Lösungen in zwei früheren Antworten Sie geben:
Es wird so etwas wie unten sein:

id   date  columnX   count>1 count_total 
1  2017-04-20  a    2   4 
1  2017-04-20  x    2   4 
2  2017-04-20  a    2   3 
2  2017-04-19  b    4   5  

Beachten Sie zwei Zeilen für ID = 1 und Datum = 2017-04-20 und beide mit count_total = 4
Ich bin mir nicht sicher, ob das ist, was Sie wollen t - auch wenn Sie dieses Szenario nicht einmal in Frage

Wie auch immer betrachtet könnte, glaube ich, dass allgemeineren Fall zu unterstützen, wie oben Ihrer Erwartung ausgegeben werden sollte wie unter

Row id date  x.columnX x.countX count_total 
1 1 2017-04-20 x   2   4  
        a   2   
2 2 2017-04-20 a   2   3  
3 2 2017-04-19 b   4   5  

wo x wiederholt Feld und jeder Wert repräsentiert jeweiligen columnX mit seiner Zählung

Below Abfrage dies tut genau

#standardSQL 
SELECT id, date, 
    ARRAY(SELECT x FROM UNNEST(x) AS x WHERE countX > 1) AS x, 
    count_total 
FROM (
    SELECT id, date, SUM(countX) AS count_total, 
    ARRAY_AGG(STRUCT<columnX STRING, countX INT64>(columnX, countX) ORDER BY countX DESC) AS X  
    FROM (
    SELECT id, date, 
     columnX, COUNT(1) countX 
    FROM `yourTable` 
    GROUP BY id, date, columnX 
) 
    GROUP BY id, date 
    HAVING count_total > 1 
) 

Sie können es spielen/Test mit Dummy-Daten von Ihrer Frage

#standardSQL 
WITH `yourTable` AS(
    SELECT 1 AS id, '2017-04-20' AS date, 'a' AS columnX UNION ALL 
    SELECT 1, '2017-04-20', 'a' UNION ALL 
    SELECT 1, '2017-04-20', 'x' UNION ALL 
    SELECT 1, '2017-04-20', 'x' UNION ALL 
    SELECT 1, '2017-04-18', 'b' UNION ALL 
    SELECT 1, '2017-04-17', 'c' UNION ALL 
    SELECT 2, '2017-04-20', 'a' UNION ALL 
    SELECT 2, '2017-04-20', 'a' UNION ALL 
    SELECT 2, '2017-04-20', 'c' UNION ALL 
    SELECT 2, '2017-04-19', 'b' UNION ALL 
    SELECT 2, '2017-04-19', 'b' UNION ALL 
    SELECT 2, '2017-04-19', 'b' UNION ALL 
    SELECT 2, '2017-04-19', 'b' UNION ALL 
    SELECT 2, '2017-04-19', 'c' 
) 
SELECT id, date, 
    ARRAY(SELECT x FROM UNNEST(x) AS x WHERE countX > 1) AS x, 
    count_total 
FROM (
    SELECT id, date, SUM(countX) AS count_total, 
    ARRAY_AGG(STRUCT<columnX STRING, countX INT64>(columnX, countX) ORDER BY countX DESC) AS X  
    FROM (
    SELECT id, date, 
     columnX, COUNT(1) countX 
    FROM `yourTable` 
    GROUP BY id, date, columnX 
) 
    GROUP BY id, date 
    HAVING count_total > 1 
) 
Verwandte Themen