2017-07-28 1 views
0

Ich habe 3 sehr große Tabellen * von IP-Adressen und versuche, die Anzahl der gemeinsamen IPs zwischen den 3 Tabellen zu zählen. Ich habe überlegt, Joins und auch eine Unterabfrage zu verwenden, um den Schnittpunkt von IPs zwischen diesen 3 Tabellen zu finden. Wie kann ich die Schnittmenge aller 3 Tabellen mit einer Abfrage finden?Wie kann ich 3 große Tabellen für überschneidende Werte mit Hilfe von Hive abfragen?

Dies ist falsche Syntax, sondern zeigt, was ich versuche zu erreichen:

SELECT COUNT(DISTINCT(a.ip)) FROM a, b, c WHERE a.ip = b.ip = c.ip 

ich andere Antworten zu haben gesehen, wie drei Tabellen zu verknüpfen, aber nichts für Hive und nichts für diese Skala.

* Anmerkungen:

  • Tabelle a: 7 Milliarden Zeilen
  • Tabelle b: 1,8 Milliarden Zeilen
  • Tabelle c: 168 Millionen Zeilen
  • 'Tables' sind eigentlich hive Metastore unterstützt von S3 .
  • Es gibt viele doppelte IPs in jeder Tabelle
  • Leistung Vorschläge willkommen.
  • Auch können Spark SQL-Abfragen ausführen, wenn es anstelle von Hive eine bessere Idee ist.

Antwort

1

Eine einfache Lösung:

select  count(*) 

from  (select  1 

      from  (
            select 'a' as tab,ip from a 
         union all select 'b' as tab,ip from b 
         union all select 'c' as tab,ip from c 
         ) t 

      group by ip 

      having  count(case when tab = 'a' then 1 end) > 0 
        and count(case when tab = 'b' then 1 end) > 0 
        and count(case when tab = 'c' then 1 end) > 0 

      ) t 

Dies wird Ihnen nicht nur Informationen über die 3 Tabellen Kreuzung (IN_A = 1, IN_B = 1, in_c = 1), sondern auch Informationen über alle anderen Kombinationen:

select  in_a 
      ,in_b 
      ,in_c 
      ,count(*) as ips 

from  (select  max(case when tab = 'a' then 1 end) as in_a 
         ,max(case when tab = 'b' then 1 end) as in_b 
         ,max(case when tab = 'c' then 1 end) as in_c 

      from  (
            select 'a' as tab,ip from a 
         union all select 'b' as tab,ip from b 
         union all select 'c' as tab,ip from c 
         ) t 

      group by ip 
      ) t 

group by in_a 
      ,in_b 
      ,in_c 

... und noch einige weitere Informationen:

select  sign(cnt_a)     as in_a 
      ,sign(cnt_b)     as in_b 
      ,sign(cnt_c)     as in_c 

      ,count(*)     as unique_ips 
      ,sum(cnt_total)    as total_ips 
      ,sum(cnt_a)     as total_ips_in_a 
      ,sum(cnt_b)     as total_ips_in_b 
      ,sum(cnt_c)     as total_ips_in_c 

from  (select  count(*)        as cnt_total 
         ,count(case when tab = 'a' then 1 end) as cnt_a 
         ,count(case when tab = 'b' then 1 end) as cnt_b 
         ,count(case when tab = 'c' then 1 end) as cnt_c 

      from  (
            select 'a' as tab,ip from a 
         union all select 'b' as tab,ip from b 
         union all select 'c' as tab,ip from c 
         ) t 

      group by ip 
      ) t 

group by sign(cnt_a) 
      ,sign(cnt_b) 
      ,sign(cnt_c) 
+0

upvote weil a) die Syntax gearbeitet und b) Rache ist lahm downvotes. – TheProletariat

+1

@DuduMarkovitz Ich nahm es nicht persönlich - ich entfernte meine Antwort, weil es zwei bessere Antworten gab, und meine hat nicht viel hinzugefügt. Ich habe dich nicht abgelehnt. – Siyual

+0

@DuduMarkovitz das funktioniert gut, aber wie bekomme ich dann eine Zählung von allen, die in allen 3 Tabellen existieren? Kann ich einfach eine Auswahlzählung (*) von anwählen, wobei in_a = 1 und in_b = 1 und in_c = 1, oder gibt es einen besseren Weg? – TheProletariat

3

Die korrekte Syntax ist:

SELECT COUNT(DISTINCT a.ip) 
FROM a JOIN 
    b 
    ON a.ip = b.ip JOIN 
    c 
    ON a.ip = c.ip; 

Das wird wahrscheinlich nicht in unserem Leben zu beenden. Ein besserer Ansatz ist:

select ip 
from (select distinct a.ip, 1 as which from a union all 
     select distinct b.ip, 2 as which from b union all 
     select distinct c.ip, 3 as which from c 
    ) abc 
group by ip 
having sum(which) = 6; 

zugelassen sind, wird die sum(which) = 6 nur sagen, dass alle drei vorhanden sind. Wegen der select distinct in den Unterabfragen, können Sie einfach tun:

having count(*) = 3 
+0

Tatsächliche lol auf den ersten Kommentar. Ich werde das 2. versuchen und zu dir zurückkommen, wenn es in 16 Stunden oder so beendet wird. – TheProletariat

+0

Die Hive-Abfrage-Engine mag diese Syntax nicht ... Ich habe sie wortwörtlich kopiert (ich habe 3 Tabellen erstellt, die wörtlich als a, b und c mit einem Feld namens IP bezeichnet werden). Irgendwelche Vorschläge? Syntaxfehler: org.apache.hadoop.hive.ql.parse.ParseException: Zeile 2: 6 kann Eingaben in der Nähe von '(' '(' 'select' in from source) nicht erkennen – TheProletariat

+0

@Gordon Ich bin gespannt: Wie kommt es an, dass Sie 'angeben a.ip', 'b.ip' und' c.ip' in Ihren Unterabfragen hier statt nur "ip"? Sie wählen nur aus einer einzigen Tabelle. Ist dies eine "Best Practice", die ich habe – RToyo

Verwandte Themen