简体   繁体   English

postgresql:通过左连接添加两个表的列并在使用时

[英]postgresql:add columns by left join two table and using case when

there are tableA and tableB,looks like: 有tableA和tableB,看起来像:

 tableA
+--------+------------+
| cst_id |   date01   |
+--------+------------+
|      1 | 2010/9/3   |
|      2 | 2010/12/26 |
|      3 | 2010/10/5  |
|      4 | 2010/11/27 |
|      2 | 2010/11/24 |
|      2 | 2010/7/14  |
|      3 | 2010/7/25  |
|      1 | 2010/11/15 |
|      1 | 2010/11/17 |
|      4 | 2010/8/11  |
|      5 | 2010/9/17  |
|      5 | 2010/9/27  |
|      6 | 2010/11/18 |
+--------+------------+

tableB
+--------+------------+-------+-----------+
| cst_id |   date02   | money | fund_type |
+--------+------------+-------+-----------+
|      1 | 2010/7/19  |    12 | A         |
|      1 | 2010/10/27 |    44 | A         |
|      2 | 2010/10/23 |     3 | A         |
|      3 | 2010/11/27 |     6 | B         |
|      3 | 2010/12/21 |    78 | C         |
|      2 | 2010/11/18 |    45 | C         |
|      4 | 2010/11/14 |   108 | B         |
|      1 | 2010/10/24 |    11 | A         |
|      2 | 2010/12/15 |    62 | D         |
|      3 | 2010/12/4  |    43 | C         |
|      4 | 2010/9/21  |   213 | C         |
+--------+------------+-------+-----------+

tableA is an ordinary customer table,and tableB is a fund dealing fact table.how to create columns:60tol_money(within 60 days before date01,how much money spend on fund),60tol_type(within 60 days before date01,how many types have been bought);60_days(60 days before date01,how many dealings have been made),and get: tableA是普通客户表,tableB是资金交易事实表。如何创建列:60tol_money(date01之前60天之内,有多少资金花在资金上),60tol_type(date01之前60天之内,有多少种类型)购买); 60天(在date01之前60天,已经完成了多少笔交易),并获得:

tableC

+--------+------------+-------------+------------+---------+---------+---------+
| cst_id |   date01   | 60tol_money | 60tol_type | 14_days | 30_days | 60_days |
+--------+------------+-------------+------------+---------+---------+---------+
|      1 | 2010/9/3   | 12          | 1          |       1 |       1 |       1 |
|      2 | 2010/12/26 | 45+62       | 2(C+D)     |       1 |       1 |       2 |
|      3 | 2010/10/5  |             |            |         |         |         |
|      4 | 2010/11/27 |             |            |         |         |         |
|      2 | 2010/11/24 |             |            |         |         |         |
|      2 | 2010/7/14  |             |            |         |         |         |
|      3 | 2010/7/25  |             |            |         |         |         |
|      1 | 2010/11/15 |             |            |         |         |         |
|      1 | 2010/11/17 |             |            |         |         |         |
|      4 | 2010/8/11  |             |            |         |         |         |
|      5 | 2010/9/17  | 0           | 0          |       0 |       0 |       0 |
|      5 | 2010/9/27  | 0           | 0          |       0 |       0 |       0 |
|      6 | 2010/11/18 | 0           | 0          |       0 |       0 |       0 |
+--------+------------+-------------+------------+---------+---------+---------+

Here's a partial query, see how it works for you. 这是部分查询,查看它如何为您工作。 The rest you can probably figure out yourself based on this. 其余的您可能可以根据此来弄清楚自己。

SELECT
    a.cst_id,
    a.date01,
    SUM(CASE WHEN b.date02 BETWEEN a.date01 - 60 AND a.date01 THEN b.money ELSE 0 END) AS "60tol_money",
    COUNT(DISTINCT CASE WHEN b.date02 BETWEEN a.date01 - 60 AND a.date01 THEN b.fund_type END) AS "60tol_type"
FROM tableA a 
LEFT JOIN tableB b USING (cst_id)
GROUP BY a.cst_id, a.date01
ORDER BY a.cst_id, a.date01

Briefly, to get 60tol_money, if date02 is within 60 days of date01, then add that record's money value to the sum. 简而言之,要获取60tol_money,如果date02在date01的60天内,则将该记录的货币值加到总和上。 If not, a zero is added to the sum instead. 如果不是,则将零加到总和上。 For the fund type, again check the date, if valid then use the fund_type value, else NULL (implied, since I didn't put an ELSE in there). 对于基金类型,再次检查日期(如果有效),然后使用fund_type值,否则使用NULL(暗示,因为我没有在其中放置ELSE)。 Then only the distinct fund types are counted (NULL doesn't count), to get the 60tol_type value. 然后,仅计算不同的基金类型(不计算NULL),以获得60tol_type值。

If you are using PostgreSQL 9.4 and higher, then it's possible to optimize @eurotrash 's query with FILTER WHERE clause like this: 如果您使用的是PostgreSQL 9.4和更高版本,则可以使用FILTER WHERE子句来优化@eurotrash的查询,如下所示:

SELECT
    a.cst_id,
    a.date01,
    SUM(b.money) FILTER (WHERE b.date02 BETWEEN a.date01 - 60 AND a.date01) AS "60tol_money",
    COUNT(DISTINCT b.fund_type) FILTER (WHERE b.date02 BETWEEN a.date01 - 60 AND a.date01) AS "60tol_type"
FROM tableA a 
LEFT JOIN tableB b USING (cst_id)
GROUP BY a.cst_id, a.date01
ORDER BY a.cst_id, a.date01

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM