需要帮助在一行中的两个日期之间为每个月创建多行
Need assistance creating multiple rows for every month between two dates in one row
我正在尝试创建一个显示每个月的月收入的仪表板。我认为最好的方法是创建一个 table,每个月都有一行,旁边是收入。当前一行数据如下所示:
Subscription_ID| Start_Date| End_Date |Monthly_revenue
2384105 | 1/1/2016 | 6/1/2016 |500
我想以某种方式将该行转换为如下所示:
Subscription_ID |Month |Monthly_Revenue
2384105 |1/1/2016 | 500
2384105 |2/1/2016 | 500
2384105 |3/1/2016 | 500
2384105 |4/1/2016 | 500
2384105 |5/1/2016 | 500
2384105 |6/1/2016 | 500
我什至不知道该怎么做。任何建议将不胜感激,或者如果你能指出我正确的方向。我使用 redshift 作为我的数据库,因此语法与 postgres 大体相似。
编辑:回复评论 - 如果有助于参考,我可以轻松地制作一个包含所有日期和年份的 table。
好的,我查看了一些 redshift 文档,像这样应该可以工作:
DATEDIFF http://docs.aws.amazon.com/redshift/latest/dg/r_DATEDIFF_function.html
常用 Table 表达式 http://docs.aws.amazon.com/redshift/latest/dg/r_WITH_clause.html
添加日期http://docs.aws.amazon.com/redshift/latest/dg/r_DATEADD_function.html
WITH cteData AS (
SELECT
CAST(2384105 AS INTEGER) AS Subscription_ID
,CAST('2016-01-01' AS DATE) AS Start_Date
,CAST('2016-06-01' AS DATE) AS End_Date
,CAST(500 AS INTEGER) AS Monthly_revenue
)
,cteTally AS (
SELECT 0 AS TallyNum
UNION ALL
SELECT 1
UNION ALL
SELECT 2
UNION ALL
SELECT 3
UNION ALL
SELECT 4
UNION ALL
SELECT 5
UNION ALL
SELECT 6
UNION ALL
SELECT 7
UNION ALL
SELECT 8
UNION ALL
SELECT 9
UNION ALL
SELECT 10
UNION ALL
SELECT 11
)
SELECT
Subscription_ID
,DATEADD(month,c.TallyNum,t.Start_date) AS "Month"
,Monthly_revenue
FROM
cteData t
INNER JOIN cteTally c
ON DATEDIFF(month,t.Start_Date,t.End_Date) >= c.TallyNum
这可能对您有用,因为它不使用 generate_series() 或递归 cte。这是 postgresSQL 版本 我用 SQL Fiddle (http://sqlfiddle.com/#!15/f3a23/7/0) 试过这个...
CREATE TABLE Tbl (
Subscription_ID INTEGER
,Start_Date DATE
,End_Date DATE
,Monthly_revenue INTEGER);
INSERT INTO Tbl (Subscription_ID, Start_Date, End_Date, Monthly_revenue)
VALUES (2384105,'2016-01-01','2016-06-01',500);
WITH cteTally AS (
SELECT 0 AS TallyNum
UNION ALL
SELECT 1
UNION ALL
SELECT 2
UNION ALL
SELECT 3
UNION ALL
SELECT 4
UNION ALL
SELECT 5
UNION ALL
SELECT 6
UNION ALL
SELECT 7
UNION ALL
SELECT 8
UNION ALL
SELECT 9
UNION ALL
SELECT 10
UNION ALL
SELECT 11
)
SELECT
Subscription_ID
,(t.Start_Date + (c.TallyNum * '1 month'::INTERVAL)) as "Month"
,Monthly_revenue
FROM
Tbl t
INNER JOIN cteTally c
ON (
(DATE_PART('year', t.End_Date) - DATE_PART('year', t.Start_Date)) * 12
+
(DATE_PART('month', t.End_Date) - DATE_PART('month', t.Start_Date))
) >= c.TallyNum
;
我正在尝试创建一个显示每个月的月收入的仪表板。我认为最好的方法是创建一个 table,每个月都有一行,旁边是收入。当前一行数据如下所示:
Subscription_ID| Start_Date| End_Date |Monthly_revenue
2384105 | 1/1/2016 | 6/1/2016 |500
我想以某种方式将该行转换为如下所示:
Subscription_ID |Month |Monthly_Revenue
2384105 |1/1/2016 | 500
2384105 |2/1/2016 | 500
2384105 |3/1/2016 | 500
2384105 |4/1/2016 | 500
2384105 |5/1/2016 | 500
2384105 |6/1/2016 | 500
我什至不知道该怎么做。任何建议将不胜感激,或者如果你能指出我正确的方向。我使用 redshift 作为我的数据库,因此语法与 postgres 大体相似。
编辑:回复评论 - 如果有助于参考,我可以轻松地制作一个包含所有日期和年份的 table。
好的,我查看了一些 redshift 文档,像这样应该可以工作:
DATEDIFF http://docs.aws.amazon.com/redshift/latest/dg/r_DATEDIFF_function.html
常用 Table 表达式 http://docs.aws.amazon.com/redshift/latest/dg/r_WITH_clause.html
添加日期http://docs.aws.amazon.com/redshift/latest/dg/r_DATEADD_function.html
WITH cteData AS (
SELECT
CAST(2384105 AS INTEGER) AS Subscription_ID
,CAST('2016-01-01' AS DATE) AS Start_Date
,CAST('2016-06-01' AS DATE) AS End_Date
,CAST(500 AS INTEGER) AS Monthly_revenue
)
,cteTally AS (
SELECT 0 AS TallyNum
UNION ALL
SELECT 1
UNION ALL
SELECT 2
UNION ALL
SELECT 3
UNION ALL
SELECT 4
UNION ALL
SELECT 5
UNION ALL
SELECT 6
UNION ALL
SELECT 7
UNION ALL
SELECT 8
UNION ALL
SELECT 9
UNION ALL
SELECT 10
UNION ALL
SELECT 11
)
SELECT
Subscription_ID
,DATEADD(month,c.TallyNum,t.Start_date) AS "Month"
,Monthly_revenue
FROM
cteData t
INNER JOIN cteTally c
ON DATEDIFF(month,t.Start_Date,t.End_Date) >= c.TallyNum
这可能对您有用,因为它不使用 generate_series() 或递归 cte。这是 postgresSQL 版本 我用 SQL Fiddle (http://sqlfiddle.com/#!15/f3a23/7/0) 试过这个...
CREATE TABLE Tbl (
Subscription_ID INTEGER
,Start_Date DATE
,End_Date DATE
,Monthly_revenue INTEGER);
INSERT INTO Tbl (Subscription_ID, Start_Date, End_Date, Monthly_revenue)
VALUES (2384105,'2016-01-01','2016-06-01',500);
WITH cteTally AS (
SELECT 0 AS TallyNum
UNION ALL
SELECT 1
UNION ALL
SELECT 2
UNION ALL
SELECT 3
UNION ALL
SELECT 4
UNION ALL
SELECT 5
UNION ALL
SELECT 6
UNION ALL
SELECT 7
UNION ALL
SELECT 8
UNION ALL
SELECT 9
UNION ALL
SELECT 10
UNION ALL
SELECT 11
)
SELECT
Subscription_ID
,(t.Start_Date + (c.TallyNum * '1 month'::INTERVAL)) as "Month"
,Monthly_revenue
FROM
Tbl t
INNER JOIN cteTally c
ON (
(DATE_PART('year', t.End_Date) - DATE_PART('year', t.Start_Date)) * 12
+
(DATE_PART('month', t.End_Date) - DATE_PART('month', t.Start_Date))
) >= c.TallyNum
;