在POSTGRES中加入或查询高效的SQL表?怎么做怎么办?

时间:2017-01-03 18:33:45

标签: sql postgresql join pivot crosstab

我有以下表格

表1

 ID1   YEAR1       
 1      1980 
 2      1964 
 3      1910

表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

我想加入/查询这些表格:

对于表1中的每个ID1匹配,添加一个名为VALUE的列 - 因此列名称将为A,B,......等等,该列将为TRUE(T)或FALSE(F)。

如果ID1与表2中的ID2匹配,则列A ...将为TRUE,而表2中与ID2匹配的给定行的YEAR2小于表1中给定1的值YEAR1和VALUE从表2中具有ID2的行得到A

所以结果表如下:

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

4 个答案:

答案 0 :(得分:1)

您可以使用如下查询:

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

如果,例如列A的值为1,然后将其视为T,否则将其视为F

Demo here

答案 1 :(得分:0)

你可以使用group by Giorgos或像这样加入:

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'

答案 2 :(得分:0)

我只想使用条件聚合和布尔类型:

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;

答案 3 :(得分:0)

您已将问题标记为postgresql,因此我将使用common table expressionstablefunc extension.

提供的数据透视表给出PostgreSQL答案

这实际上是在数据透视表的帮助下最佳表达的问题的典型示例。

如您所见,最乏味的部分是填充虚拟对象的空位。

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;