有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是一个普通的客户表,而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 |
+--------+------------+-------------+------------+---------+---------+---------+
答案 0 :(得分:1)
这是一个部分查询,请看它是如何运作的。其余的你可以根据这个来弄清楚自己。
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
简单地说,要获得60tol_money,如果date02在date01的60天内,则将该记录的货币值添加到总和中。如果不是,则将总和添加为零。对于基金类型,再次检查日期,如果有效则使用fund_type值,否则为NULL(暗示,因为我没有在其中放置ELSE)。然后只计算不同的基金类型(NULL不计数),以获得60tol_type值。
答案 1 :(得分:0)
如果您使用的是PostgreSQL 9.4及更高版本,则可以使用@eurotrash子句优化FILTER WHERE的查询,如下所示:
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