[英]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.