2017-06-18 2 views
1

nach einer Transformation habe ich ein Ergebnis von einem Kreuz Join (aus Tabelle a und b), wo ich eine Analyse durchführen möchte. Die Tabelle für diese sieht wie folgt aus:Vergleichen verschiedener Spalten in SQL für jede Zeile

+-----+------+------+------+------+-----+------+------+------+------+ 
| id | 10_1 | 10_2 | 11_1 | 11_2 | id | 10_1 | 10_2 | 11_1 | 11_2 | 
+-----+------+------+------+------+-----+------+------+------+------+ 
| 111 | 1 | 0 | 1 | 0 | 222 | 1 | 0 | 1 | 0 | 
| 111 | 1 | 0 | 1 | 0 | 333 | 0 | 0 | 0 | 0 | 
| 111 | 1 | 0 | 1 | 0 | 444 | 1 | 0 | 1 | 1 | 
| 112 | 0 | 1 | 1 | 0 | 222 | 1 | 0 | 1 | 0 | 
+-----+------+------+------+------+-----+------+------+------+------+ 

die IDs in der ersten Spalte unterscheiden sich von den IDs in der sechsten Spalte. In einer Reihe sind immer zwei verschiedene IDs, die miteinander übereinstimmen. Die anderen Spalten haben immer entweder 0 oder 1 als Wert.

Ich versuche jetzt herauszufinden, wie viele Werte (beide haben "1" in 10_1, 10_2 etc) haben zwei IDs im Durchschnitt gemeinsam, aber ich weiß nicht wirklich, wie es geht.

Ich war so etwas wie dies als Start versuchen:

SELECT SUM(CASE WHEN a.10_1 = 1 AND b.10_1 = 1 then 1 end) 

Aber dies offensichtlich nur würde zählen, wie oft zwei ids 10_1 gemeinsam haben.

SELECT SUM(CASE WHEN (a.10_1 = 1 AND b.10_1 = 1) 
OR (a.10_2 = 1 AND b.10_1 = 1) OR [...] then 1 end) 

zählen im Allgemeinen, wie oft zwei IDs eine gemeinsam haben, aber dies würde natürlich auch zählen, wenn sie zwei oder mehr Dinge gemeinsam: Ich könnte so etwas wie dies zum Beispiel für verschiedene Spalten machen. Außerdem würde ich gerne wissen, wie oft zwei IDS zwei Dinge, drei Dinge usw. gemeinsam haben.

Ein "Problem" in meinem Fall ist auch, dass ich ungefähr ~ 30 Spalten habe, die ich mir anschauen möchte, damit ich für jeden Fall kaum jede mögliche Kombination aufschreiben kann.

Weiß jemand, wie ich mein Problem besser angehen kann? Vielen Dank im Voraus.

Edit: Ein mögliches Ergebnis könnte wie folgt aussehen:

+-----------+---------+ 
| in_common | count | 
+-----------+---------+ 
|   0 |  100 | 
|   1 |  500 | 
|   2 | 1500 | 
|   3 | 5000 | 
|   4 | 3000 | 
+-----------+---------+ 
+0

Bearbeiten Sie Ihre Frage und zeigen die Ergebnisse, die Sie erhalten möchten. Lassen Sie mich hinzufügen, dass die "CROSS JOIN" -Ergebnisse nicht so aussehen, als ob es mit Ihrem Ziel hilft. Warum nicht diese Frage löschen? Stellen Sie eine andere Frage mit Ihren tatsächlichen Daten und einer klaren Erklärung dessen, was Sie versuchen zu tun. –

+0

Ich habe ein mögliches Ergebnis hinzugefügt. Der Grund, warum ich das Cross mitgemacht habe, ist folgender: Ich habe zwei Subsets (wie männlich und weiblich), die ich anhand einiger Kriterien zusammenbringen möchte - und zwar mit dem Cross Join und einigen Where-Klauseln. Danach bekomme ich ein Zwischenergebnis, wie oben gezeigt, wo ich wissen möchte, wie viele Werte Männer und Frauen, die zusammen passen, im Durchschnitt gemeinsam haben. – mangix

+0

Wie sehen Ihre Daten vor der Umwandlung aus? Die Lösung wäre einfacher, wenn Ihre Datentabelle zwei Spalten hätte, eine für die ID und eine für den Code (10_1, 10_2 usw.). –

Antwort

0

Mit den Codes als Spaltennamen, Sie gehen zu müssen, einige Codes schreiben, der ausdrücklich jeden Spaltennamen verweist. Zu halten, dass auf ein Minimum, könnten Sie diese Verweise in einer einzigen Gewerkschaft Anweisung schreiben, die die Daten normalisiert, wie zum Beispiel:

select id, '10_1' where "10_1" = 1 
union 
select id, '10_2' where "10_2" = 1 
union 
select id, '11_1' where "11_1" = 1 
union 
select id, '11_2' where "11_2" = 1; 

Dies muss geändert werden, enthalten, was zusätzliche Spalten Sie benötigen unterschiedliche IDs zu verknüpfen. Für die Zwecke dieser Darstellung gehe ich davon aus dem folgende Datenmodell

create table p (
    id integer not null primary key, 
    sex character(1) not null, 
    age integer not null 
    ); 

create table t1 (
    id integer not null, 
    code character varying(4) not null, 
    constraint pk_t1 primary key (id, code) 
    ); 

Obwohl Ihre Daten derzeit offenbar nicht über diese Struktur ähneln, Ihre Daten in eine Form zu normalisieren, wie dies Sie erlauben würde, die folgende Lösung anwenden zusammenzufassen Ihre Daten in der gewünschten Form.

select 
    in_common, 
    count(*) as count 
from (
    select 
     count(*) as in_common 
    from (
     select 
     a.id as a_id, a.code, 
     b.id as b_id, b.code 
     from 
     (select p.*, t1.code 
      from p left join t1 on p.id=t1.id 
      ) as a 
     inner join (select p.*, t1.code 
      from p left join t1 on p.id=t1.id 
      ) as b on b.sex <> a.sex and b.age between a.age-10 and a.age+10 
     where 
     a.id < b.id 
     and a.code = b.code 
     ) as c 
    group by 
     a_id, b_id 
    ) as summ 
group by 
    in_common; 
0

Die vorgeschlagene Lösung erfordert zunächst einen Schritt zurück von der Quer Join-Tabelle zu nehmen, da die identischen Spaltennamen Super ärgerlich sind. Stattdessen nehmen wir die id s aus den beiden Tabellen und legen sie in eine temporäre Tabelle. Die folgende Abfrage erhält das gewünschte Ergebnis in der Frage. Es wird davon ausgegangen, table_a und table_b aus der Frage sind die gleichen und tbl genannt, aber diese Annahme ist nicht erforderlich und tbl kann durch table_a und table_b in den beiden Sub-SELECT-Abfragen ersetzt werden.Es sieht kompliziert aus und verwendet die JSON Trick, um die Spalten zu glätten, aber es funktioniert hier:

WITH idtable AS (
SELECT a.id as id_1, b.id as id_2 FROM 
    -- put cross join of table a and table b here 
) 
SELECT in_common, 
     count(*) 
FROM 
    (SELECT idtable.*, 
      sum(CASE 
        WHEN meltedR.value::text=meltedL.value::text THEN 1 
        ELSE 0 
       END) AS in_common 
    FROM idtable 
    JOIN 
    (SELECT tbl.id, 
      b.* 
     FROM tbl,       -- change here to table_a 
      json_each(row_to_json(tbl)) b   -- and here too 
     WHERE KEY<>'id') meltedL ON (idtable.id_1 = meltedL.id) 
    JOIN 
    (SELECT tbl.id, 
      b.* 
     FROM tbl,       -- change here to table_b 
      json_each(row_to_json(tbl)) b   -- and here too 
     WHERE KEY<>'id') meltedR ON (idtable.id_2 = meltedR.id 
            AND meltedL.key = meltedR.key) 
    GROUP BY idtable.id_1, 
      idtable.id_2) tt 
GROUP BY in_common ORDER BY in_common; 

Die Ausgabe wie folgt hier aussieht:

in_common | count 
-----------+------- 
     2 |  2 
     3 |  1 
     4 |  1 
(3 rows) 
Verwandte Themen