Sql 同一表上的迭代查询
我有一个包含客户销售数据的表格,如下所示:Sql 同一表上的迭代查询,sql,google-bigquery,Sql,Google Bigquery,我有一个包含客户销售数据的表格,如下所示: |CustomerCode|SalesDate|Profit |123455666 |2018-06 |120 |123455666 |2018-06 |100 |123455666 |2018-05 |10 |123455666 |2018-04 |60 |666452342 |2018-06 |900 |666452342 |2018-05 |1000 |666452342 |2018-05 |900 |6
|CustomerCode|SalesDate|Profit
|123455666 |2018-06 |120
|123455666 |2018-06 |100
|123455666 |2018-05 |10
|123455666 |2018-04 |60
|666452342 |2018-06 |900
|666452342 |2018-05 |1000
|666452342 |2018-05 |900
|666452342 |2018-06 |800
我想要一张显示三个月内公司利润的表格。期望表
|CustomerCode|P_This_Month|P_1_Month_Ago|P_2_Month_Ago
|123455666 |220 |10 |60
|666452342 |900 |1900 |800
最好的方法是什么?目前我正在使用JOIN操作符。但是,即使它适用于第一个联接,也不适用于第二个联接(获得意外的高值)
我该怎么做
SELECT
This_Month.*,
SUM(_1_Month_Ago.UCSALES) sales_1_month_ago,
SUM(_2_Months_Ago.UCSALES) sales_2_months_ago
FROM
SalesTable This_Month
LEFT JOIN
SalesTable _1_Month_Ago ON This_Month.CustomerCode = _1_Month_Ago AND DATE_SUB(This_Month.SalesDate, INTERVAL 1 MONTH) = _1_Month_Ago.SalesDate
LEFT JOIN
SalesTable _2_Months_Ago ON This_Month.CustomerCode = _2_Months_Ago AND DATE_SUB(This_Month.SalesDate, INTERVAL 1 MONTH) = _2_Months_Ago.SalesDate
GROUP BY
This_Month.CustomerCode
您可以使用case when和通过从日期提取月份
with cte as
(
select EXTRACT(month FROM SalesDate) as monthofday,CustomerCode,sum(Profit) as total
from tbale
) select CustomerCode,
sum(case when monthofday=4 then total else 0 end) as Forththmonthtotal,
sum(case when monthofday=5 then total else 0 end) as fifththmonthtotal,
--you can apply for 12 month this logic
from cte
group by CustomerCode
您可以使用case when和通过从日期提取月份
with cte as
(
select EXTRACT(month FROM SalesDate) as monthofday,CustomerCode,sum(Profit) as total
from tbale
) select CustomerCode,
sum(case when monthofday=4 then total else 0 end) as Forththmonthtotal,
sum(case when monthofday=5 then total else 0 end) as fifththmonthtotal,
--you can apply for 12 month this logic
from cte
group by CustomerCode
您可以使用条件聚合来实现这一点
select
CustomerCode,
sum(case when sales_date=current_date then profit else 0 end) P_This_Month,
sum(case when sales_date=date_sub(current_date, INTERVAL 1 month) then profit else 0 end) P_1_Month,
sum(case when sales_date=date_sub(current_date, INTERVAL 2 month) then profit else 0 end) P_2_Month,
from <tableName>
group by CustomerCode
选择
客户代码,
本月P\U总额(销售日期=当前日期然后利润为0结束时的情况),
总和(销售日期=日期子项(当前日期,间隔1个月)然后利润0结束时的情况)P\u 1个月,
总和(销售日期=日期子项(当前日期,间隔2个月)然后利润0结束时的情况)P\u 2个月,
从…起
按客户代码分组
您可以通过条件聚合来实现
select
CustomerCode,
sum(case when sales_date=current_date then profit else 0 end) P_This_Month,
sum(case when sales_date=date_sub(current_date, INTERVAL 1 month) then profit else 0 end) P_1_Month,
sum(case when sales_date=date_sub(current_date, INTERVAL 2 month) then profit else 0 end) P_2_Month,
from <tableName>
group by CustomerCode
选择
客户代码,
本月P\U总额(销售日期=当前日期然后利润为0结束时的情况),
总和(销售日期=日期子项(当前日期,间隔1个月)然后利润0结束时的情况)P\u 1个月,
总和(销售日期=日期子项(当前日期,间隔2个月)然后利润0结束时的情况)P\u 2个月,
从…起
按客户代码分组
下面是针对BigQuery标准SQL的
此解决方案避免了进行自联接,并且具有足够的通用性,可以覆盖多个月的数据
#standardSQL
WITH months AS (
SELECT FORMAT_DATE('%Y-%m', month) month
FROM (
SELECT
MIN(PARSE_DATE('%Y-%m', SalesDate)) min_month,
MAX(PARSE_DATE('%Y-%m', SalesDate)) max_month
FROM `project.dataset.table`
), UNNEST(GENERATE_DATE_ARRAY(min_month, max_month, INTERVAL 1 MONTH)) month
)
SELECT CustomerCode, month,
SUM(IF(diff = 0, P_This_Month, 0)) P_This_Month,
SUM(IF(diff = 1, P_This_Month, 0)) P_1_Month_Ago,
SUM(IF(diff = 2, P_This_Month, 0)) P_2_Month_Ago
FROM (
SELECT CustomerCode, P_This_Month, PARSE_DATE('%Y-%m', month) month,
DATE_DIFF(PARSE_DATE('%Y-%m', month), PARSE_DATE('%Y-%m', SalesDate), MONTH) diff
FROM months m CROSS JOIN (
SELECT CustomerCode, SalesDate, SUM(Profit) P_This_Month
FROM `project.dataset.table`
GROUP BY CustomerCode, SalesDate
) t
)
WHERE diff BETWEEN 0 AND 2
GROUP BY CustomerCode, month
您可以使用问题中的示例数据测试、播放上述内容,如下例所示
#standardSQL
WITH `project.dataset.table` AS (
SELECT 123455666 CustomerCode, '2018-06' SalesDate, 120 Profit UNION ALL
SELECT 123455666, '2018-06', 100 UNION ALL
SELECT 123455666, '2018-05', 10 UNION ALL
SELECT 123455666, '2018-04', 60 UNION ALL
SELECT 666452342, '2018-06', 900 UNION ALL
SELECT 666452342, '2018-05', 1000 UNION ALL
SELECT 666452342, '2018-05', 900 UNION ALL
SELECT 666452342, '2018-04', 800
), months AS (
SELECT FORMAT_DATE('%Y-%m', month) month
FROM (
SELECT
MIN(PARSE_DATE('%Y-%m', SalesDate)) min_month,
MAX(PARSE_DATE('%Y-%m', SalesDate)) max_month
FROM `project.dataset.table`
), UNNEST(GENERATE_DATE_ARRAY(min_month, max_month, INTERVAL 1 MONTH)) month
)
SELECT CustomerCode, month,
SUM(IF(diff = 0, P_This_Month, 0)) P_This_Month,
SUM(IF(diff = 1, P_This_Month, 0)) P_1_Month_Ago,
SUM(IF(diff = 2, P_This_Month, 0)) P_2_Month_Ago
FROM (
SELECT CustomerCode, P_This_Month, PARSE_DATE('%Y-%m', month) month,
DATE_DIFF(PARSE_DATE('%Y-%m', month), PARSE_DATE('%Y-%m', SalesDate), MONTH) diff
FROM months m CROSS JOIN (
SELECT CustomerCode, SalesDate, SUM(Profit) P_This_Month
FROM `project.dataset.table`
GROUP BY CustomerCode, SalesDate
) t
)
WHERE diff BETWEEN 0 AND 2
GROUP BY CustomerCode, month
-- ORDER BY CustomerCode, month
结果
Row CustomerCode month P_This_Month P_1_Month_Ago P_2_Month_Ago
1 123455666 2018-04-01 60 0 0
2 123455666 2018-05-01 10 60 0
3 123455666 2018-06-01 220 10 60
4 666452342 2018-04-01 800 0 0
5 666452342 2018-05-01 1900 800 0
6 666452342 2018-06-01 900 1900 800
下面是BigQuery标准SQL 此解决方案避免了进行自联接,并且具有足够的通用性,可以覆盖多个月的数据
#standardSQL
WITH months AS (
SELECT FORMAT_DATE('%Y-%m', month) month
FROM (
SELECT
MIN(PARSE_DATE('%Y-%m', SalesDate)) min_month,
MAX(PARSE_DATE('%Y-%m', SalesDate)) max_month
FROM `project.dataset.table`
), UNNEST(GENERATE_DATE_ARRAY(min_month, max_month, INTERVAL 1 MONTH)) month
)
SELECT CustomerCode, month,
SUM(IF(diff = 0, P_This_Month, 0)) P_This_Month,
SUM(IF(diff = 1, P_This_Month, 0)) P_1_Month_Ago,
SUM(IF(diff = 2, P_This_Month, 0)) P_2_Month_Ago
FROM (
SELECT CustomerCode, P_This_Month, PARSE_DATE('%Y-%m', month) month,
DATE_DIFF(PARSE_DATE('%Y-%m', month), PARSE_DATE('%Y-%m', SalesDate), MONTH) diff
FROM months m CROSS JOIN (
SELECT CustomerCode, SalesDate, SUM(Profit) P_This_Month
FROM `project.dataset.table`
GROUP BY CustomerCode, SalesDate
) t
)
WHERE diff BETWEEN 0 AND 2
GROUP BY CustomerCode, month
您可以使用问题中的示例数据测试、播放上述内容,如下例所示
#standardSQL
WITH `project.dataset.table` AS (
SELECT 123455666 CustomerCode, '2018-06' SalesDate, 120 Profit UNION ALL
SELECT 123455666, '2018-06', 100 UNION ALL
SELECT 123455666, '2018-05', 10 UNION ALL
SELECT 123455666, '2018-04', 60 UNION ALL
SELECT 666452342, '2018-06', 900 UNION ALL
SELECT 666452342, '2018-05', 1000 UNION ALL
SELECT 666452342, '2018-05', 900 UNION ALL
SELECT 666452342, '2018-04', 800
), months AS (
SELECT FORMAT_DATE('%Y-%m', month) month
FROM (
SELECT
MIN(PARSE_DATE('%Y-%m', SalesDate)) min_month,
MAX(PARSE_DATE('%Y-%m', SalesDate)) max_month
FROM `project.dataset.table`
), UNNEST(GENERATE_DATE_ARRAY(min_month, max_month, INTERVAL 1 MONTH)) month
)
SELECT CustomerCode, month,
SUM(IF(diff = 0, P_This_Month, 0)) P_This_Month,
SUM(IF(diff = 1, P_This_Month, 0)) P_1_Month_Ago,
SUM(IF(diff = 2, P_This_Month, 0)) P_2_Month_Ago
FROM (
SELECT CustomerCode, P_This_Month, PARSE_DATE('%Y-%m', month) month,
DATE_DIFF(PARSE_DATE('%Y-%m', month), PARSE_DATE('%Y-%m', SalesDate), MONTH) diff
FROM months m CROSS JOIN (
SELECT CustomerCode, SalesDate, SUM(Profit) P_This_Month
FROM `project.dataset.table`
GROUP BY CustomerCode, SalesDate
) t
)
WHERE diff BETWEEN 0 AND 2
GROUP BY CustomerCode, month
-- ORDER BY CustomerCode, month
结果
Row CustomerCode month P_This_Month P_1_Month_Ago P_2_Month_Ago
1 123455666 2018-04-01 60 0 0
2 123455666 2018-05-01 10 60 0
3 123455666 2018-06-01 220 10 60
4 666452342 2018-04-01 800 0 0
5 666452342 2018-05-01 1900 800 0
6 666452342 2018-06-01 900 1900 800
如果您在
| 666452342 | 2018-06 | 800
上的样本数据正确无误,则销售日期
是一个文本列?@D-Shih我刚刚编写了数据。这不是实际数据。@TimBiegeleisen不,如果您在|666452342 | 2018-06 | 800
上的样本数据正确,则这是日期时间类型,是销售日期
一个文本列?@D-Shih我刚刚编造的数据。它不是实际数据。@TimBiegeleisen否,它是日期\时间类型