You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Redshift中基于起始日期生成递增日期行:用户订阅表按月拆分需求实现

Split Subscription Records into Monthly Rows in Redshift

Hey there! I know splitting subscription data into individual monthly rows can be a pain in Redshift since generate_series isn't consistently reliable. Let's walk through a solid workaround using a number series table—this approach works every time, even without generate_series.

The Approach

Since we can't rely on generate_series, we'll create a temporary (or permanent) list of sequential numbers to act as month offsets. We'll join this list to your subscription table, then calculate each month's start date and adjust the payment amount as needed.

Full SQL Solution

First, here's the query that will produce exactly the output you're looking for:

WITH numbers AS (
    -- Create a list of numbers starting at 0, extend this if you have longer subscriptions
    SELECT 0 AS n UNION ALL
    SELECT 1 UNION ALL
    SELECT 2 UNION ALL
    SELECT 3 UNION ALL
    SELECT 4 UNION ALL
    SELECT 5
)
SELECT 
    t.userid,
    -- Only show the paid amount for the first month, set others to 0
    CASE WHEN n.n = 0 THEN t.amount_paid ELSE 0 END AS amount_paid,
    -- Calculate the start date for each month by adding the offset
    DATEADD(month, n.n, t.start_date) AS start_date,
    t.months
FROM your_subscription_table t
-- Join to get one row per month in the subscription term
JOIN numbers n ON n.n < t.months
ORDER BY userid, start_date;

Breakdown of the Query

  • Numbers CTE: This creates a temporary list of integers starting at 0. If you have subscriptions longer than 6 months, just add more SELECT X UNION ALL lines to cover the maximum possible months value in your table.
  • DATEADD: This function shifts the original start_date by n months to get the first day of each subsequent month in the subscription.
  • CASE Statement: Ensures only the first month (offset 0) shows the actual amount_paid—all other months get set to 0, matching your desired output.
  • Join Condition: n.n < t.months guarantees we generate exactly months rows per original record (e.g., a 3-month subscription becomes 3 rows).

Optimize for Larger Datasets

If you're working with a lot of data or have long-term subscriptions, create a permanent number series table instead of using a CTE—it's more efficient:

-- Create a permanent number table (adjust the range to fit your needs)
CREATE TABLE number_series (n INT PRIMARY KEY);

-- Insert sequential numbers (you can automate this with a loop if needed)
INSERT INTO number_series VALUES
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9), (10),
(11), (12), ..., (120); -- Covers up to 10 years of subscriptions

Then modify the original query to use this table instead of the CTE:

SELECT 
    t.userid,
    CASE WHEN ns.n = 0 THEN t.amount_paid ELSE 0 END AS amount_paid,
    DATEADD(month, ns.n, t.start_date) AS start_date,
    t.months
FROM your_subscription_table t
JOIN number_series ns ON ns.n < t.months
ORDER BY userid, start_date;

Verify the Output

Using your sample data, this query will return exactly what you're expecting:

useridamount_paidstart_datemonths
asdf20.002020-01-011
qwer10.002021-06-013
qwer02021-07-013
qwer02021-08-013

内容的提问来源于stack exchange,提问作者NeonBlueHair

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.01 02:03:12