自我加入和总结

时间:2018-01-11 15:59:05

标签: sql postgresql

我有一个表table_one,其中记录可以是子记录,也可以是另一记录的父记录。

我正在尝试为TABLE_ONE中的每条记录获取附加记录(用户)中包含的列(点)的SUM。

我尝试了一些事情,比如自我加入,甚至在Postgres中使用RECURSIVE CTE但没有任何成功。

在下表中,记录3是记录1的子项。

TABLE_ONE

+------------------+
|ID|NAME |PARENT_ID|
+------------------+
|1 |name1|         |
+------------------+
|2 |name2|         |
+------------------+
|3 |name3|1        |
+------------------+

TABLE_TWO

+-----------------------+
|ID|TABLE_ONE_ID|USER_ID|
+-----------------------+
|1 |1           |1      |
+-----------------------+
|2 |1           |2      |
+-----------------------+
|3 |3           |3      |
+-----------------------+
|4 |2           |4      |
+-----------------------+

表用户

+---------+
|ID|POINTS|
+---------+
|1 |100   |
+---------+
|2 |200   |
+---------+
|3 |100   |
+---------+
|4 |50    |
+---------+

例外结果:

+---------------+
|ID|NAME |POINTS|
+---------------+
|1 |name1|400   |
+---------------+
|2 |name2|50    |
+---------------+

1 个答案:

答案 0 :(得分:0)

首先获得父总计:

SELECT ID, NAME, SUM(POINTS) as POINTS
FROM TABLE_ONE T1
JOIN TABLE_TWO T2 on T1.ID = T2.TABLE_ONE_ID
JOIN TABLE_USERS U on T2.USER_ID = U.ID
WHERE PARENT_ID IS NULL --assuming those are nulls in table_one, not ''
GROUP BY ID, NAME

然后获取每个父母的孩子总数:

SELECT SUM(POINTS) as POINTS, PARENT_ID
FROM TABLE_ONE T1
JOIN TABLE_TWO T2 on T1.ID = T2.TABLE_ONE_ID
JOIN TABLE_USERS U on T2.USER_ID = U.ID
WHERE PARENT_ID IS NOT NULL
GROUP BY PARENT_ID

然后合并查询并添加POINTS

SELECT P.ID, P.NAME, PARENT_POINTS + COALESCE(CHILD_POINTS,0) as POINTS
FROM (SELECT T1.ID, NAME, SUM(POINTS) as PARENT_POINTS
      FROM TABLE_ONE T1
      JOIN TABLE_TWO T2 on T1.ID = T2.TABLE_ONE_ID
      JOIN TABLE_USERS U on T2.USER_ID = U.ID
      WHERE PARENT_ID IS NULL --assuming those are nulls in table_one, not ''
      GROUP BY ID, NAME) P
LEFT JOIN (SELECT SUM(POINTS) as CHILD_POINTS, PARENT_ID
           FROM TABLE_ONE T1
           JOIN TABLE_TWO T2 on T1.ID = T2.TABLE_ONE_ID
           JOIN TABLE_USERS U on T2.USER_ID = U.ID
           WHERE PARENT_ID IS NOT NULL
           GROUP BY PARENT_ID) C on P.ID = C.PARENT_ID

一对夫妇注意到:

  • 派生表对于确保父级子连接是1到1非常重要,否则您将获得重复
  • 两者之间需要LEFT JOIN,因此您不会失去没有孩子的父母,因此您需要NULL处理POINTS(即COALESCE