2017-01-03 8 views
2

je les tableaux ci-dessousTable jointive SQL efficace ou requête dans POSTGRES? Comment et quoi faire?

tableau 1

ID1 YEAR1  
1  1980 
2  1964 
3  1910 

Tableau 2

ID2 YEAR2 VALUE 
1  2000  A 
1  1900  B 
2  1950  C 
2  1900  B 
3  2000  C 
3  1970  B 
4  1900  D 
4  1800  E 

Je voudrais joindre/interroger ces tables à:

pour chaque ID1 dans le tableau 1 match, ajoutez une colonne nommée VALUE - de sorte que les noms de colonnes soient A, B, ... et ainsi de suite, et que la colonne soit TRUE (T) ou FALSE (F). La colonne A ... serait VRAIE s'il y avait ID1 correspondant à ID2 de la table 2, et YEAR2 pour cette ligne donnée dans la table 2 qui correspondait à ID2 était inférieure à YEAR1 de cette table 1 ayant donné 1, et valeur de la ligne ayant ID2 à partir du tableau 2 avait une

donc la table résultante serait la suivante:

ID1 YEAR1  A B C D E   

1  1980 F T F F F 
2  1964 F T T F F 
3  1910 F F F F F 
+1

Quel SGBD utilisez-vous? –

+1

vous aurez besoin de faire un tableau croisé dynamique, il y a plusieurs façons de le faire. Quel DB utilisez-vous – markg

+0

Pas de SGBD spécifié, pas de requête ou de journal des erreurs pour vérifier – Alfabravo

Répondre

1

Vous pouvez utiliser une requête comme suit:

SELECT t1.ID1, t1.YEAR1, 
     COUNT(CASE WHEN t2.VALUE = 'A' AND t1.YEAR1 > t2.YEAR2 THEN 1 END) AS A, 
     COUNT(CASE WHEN t2.VALUE = 'B' AND t1.YEAR1 > t2.YEAR2 THEN 1 END) AS B, 
     COUNT(CASE WHEN t2.VALUE = 'C' AND t1.YEAR1 > t2.YEAR2 THEN 1 END) AS C, 
     COUNT(CASE WHEN t2.VALUE = 'D' AND t1.YEAR1 > t2.YEAR2 THEN 1 END) AS D, 
     COUNT(CASE WHEN t2.VALUE = 'E' AND t1.YEAR1 > t2.YEAR2 THEN 1 END) AS E, 
     COUNT(CASE WHEN t2.VALUE = 'F' AND t1.YEAR1 > t2.YEAR2 THEN 1 END) AS F  
FROM Table1 AS t1 
LEFT JOIN Table2 AS t2 ON t1.ID1 = t2.ID2 
GROUP BY t1.ID1, t1.YEAR1 

Si e. g. La valeur de la colonne A est 1, alors elle est considérée comme T, sinon elle est considérée comme F.

Demo here

+0

wow merci:) superbe – suprvisr

+0

comment toujours voudrais apprendre, pourquoi utiliser la jointure gauche au lieu de la simple jointure? et si nous ne nous joignons pas? il suffit de sélectionner? – suprvisr

+0

@suprvisr Vous devez 'JOIN 'd'une façon ou d'une autre pour obtenir les informations sur la colonne' VALUE' de 'table2'. Vous devez également utiliser un 'LEFT JOIN', car vous obtiendrez ainsi toutes les valeurs de * t1.ID1, t1.YEAR1', même s'il n'y a pas de correspondance dans' table2'. –

0

Vous pouvez utiliser le groupe par comme Giorgos ou rejoint comme ceci:

SELECT T1.ID1, T1.YEAR1 
FROM TABLE1 T1 
LEFT JOIN TABLE2 A ON T1.ID1 =SELECT T1.ID1, T1.YEAR1, 
     CASE WHEN A.ID2 IS NOT NULL THEN 'T' ELSE 'F' END AS A, 
     CASE WHEN B.ID2 IS NOT NULL THEN 'T' ELSE 'F' END AS B, 
     CASE WHEN C.ID2 IS NOT NULL THEN 'T' ELSE 'F' END AS C, 
     CASE WHEN D.ID2 IS NOT NULL THEN 'T' ELSE 'F' END AS D, 
     CASE WHEN E.ID2 IS NOT NULL THEN 'T' ELSE 'F' END AS E 
FROM TABLE1 T1 
LEFT JOIN TABLE2 A ON T1.ID1 = A.ID2 AND T1.YEAR1 > A.YEAR2 AND A.VALUE = 'A' 
LEFT JOIN TABLE2 B ON T1.ID1 = B.ID2 AND T1.YEAR1 > B.YEAR2 AND B.VALUE = 'B' 
LEFT JOIN TABLE2 C ON T1.ID1 = C.ID2 AND T1.YEAR1 > C.YEAR2 AND C.VALUE = 'C' 
LEFT JOIN TABLE2 D ON T1.ID1 = D.ID2 AND T1.YEAR1 > D.YEAR2 AND D.VALUE = 'D' 
LEFT JOIN TABLE2 E ON T1.ID1 = E.ID2 AND T1.YEAR1 > E.YEAR2 AND E.VALUE = 'E' 
+0

wow merci:) superbe – suprvisr

0

Je voudrais simplement utiliser l'agrégation conditionnelle et les types booléens:

SELECT t1.id1, 
     BOOL_OR((t2.VALUE = 'A' AND t2.YEAR < t1.YEAR)) as A, 
     BOOL_OR((t2.VALUE = 'B' AND t2.YEAR < t1.YEAR)) as B, 
     BOOL_OR((t2.VALUE = 'C' AND t2.YEAR < t1.YEAR)) as C, 
     BOOL_OR((t2.VALUE = 'D' AND t2.YEAR < t1.YEAR)) as D, 
     BOOL_OR((t2.VALUE = 'E' AND t2.YEAR < t1.YEAR)) as E, 
     BOOL_OR((t2.VALUE = 'F' AND t2.YEAR < t1.YEAR)) as F 
FROM Table1 t1 LEFT JOIN 
    Table2 t2 
    ON t1.ID1 = t2.ID2 
GROUP BY t1.ID1; 
+0

merci - pourquoi utiliser la jointure gauche au lieu de la simple jointure? et si nous ne nous joignons pas? il suffit de sélectionner? – suprvisr

+0

@suprvisr. . . La 'jointure gauche 'est dans le cas où certains identifiants dans' table1' n'ont aucune ligne correspondante dans 'table2'. –

+0

S'il vous plaît aider avec cela, aussi, peut vous prendre 1 minute http://stackoverflow.com/questions/41455107/complex-posgresql-query-help-needed?noredirect=1#comment70117297_41455107 – suprvisr

0

Vous avez marqué votre question comme postgresql donc je vais donner une réponse PostgreSQL, avec common table expressions et un tableau croisé dynamique tel que fourni par le tablefunc extension.

Il s'agit en fait d'un exemple typique de problèmes qui s'expriment le mieux à l'aide de tableaux croisés dynamiques. Comme vous le voyez, la partie la plus fastidieuse est de remplir les falses là où la table pivotante a des zéros.

CREATE EXTENSION tablefunc; -- If you haven’t already 

WITH ct AS (
    SELECT * FROM CROSSTAB (
    'SELECT id2, t1.year1, t2.value, t2.year2 < t1.year1 
     FROM t2 JOIN t1 ON t1.id1 = t2.id2 ORDER BY 1,3', 
    $$VALUES('A'::CHAR(1)),('B'),('C'),('D'),('E')$$)   
    AS ct("ID1" INT, "YEAR1" INT, 
     "A" BOOL, "B" BOOL, "C" BOOL, "D" BOOL, "E" BOOL) 
) SELECT "ID1", "YEAR1", 
     ("A" AND ("A" IS NOT NULL)) AS "A", 
     ("B" AND ("B" IS NOT NULL)) AS "B", 
     ("C" AND ("C" IS NOT NULL)) AS "C", 
     ("D" AND ("D" IS NOT NULL)) AS "D", 
     ("E" AND ("E" IS NOT NULL)) AS "E", 
    FROM ct; 
+0

Qu'est-ce que CTE :) et crosstab :) désolé très nouveau pour tout :)? Je vous remercie! – suprvisr

+0

CTE sont [Expressions de table communes] (https://www.postgresql.org/docs/9.6/static/queries-with.html); 'CROSSTAB' est une fonction fournie par [l'extension standard tablefunc] (https://www.postgresql.org/docs/9.6/static/tablefunc.html) – Dario

+0

Les balises' pivot' et 'crosstab' n'ont-elles pas été ajoutées par toi? – Dario