1

I have a table and I want to create 5 rows with respect to id and week. for example

input table

id  week   value
1  2022-W1 200
2  2022-W3 500
2  2022-W6 600

output

id  week   value
1  2022-W1 200
1  2022-W2 200
1  2022-W3 200
1  2022-W4 200
1  2022-W5 200
2  2022-W3 500
2  2022-W4 500
2  2022-W5 500
2  2022-W6 600
2  2022-W7 600
2  2022-W8 600
2  2022-W9 600
2  2022-W10 600

Explanation -
for id = 1, w1 -> add 5 rows incremental to week

1  2022-W1 200
1  2022-W2 200
1  2022-W3 200
1  2022-W4 200
1  2022-W5 200

There are 2 rows for id = 2, (w3, and w6). for w3, there will be only 3 rows because 4 rows should be w6 and w6 is already present in the table.

2  2022-W3 500
2  2022-W4 500
2  2022-W5 500

for id=2, w6 -> add 5 rows incremental to week

2  2022-W6 600
2  2022-W7 600
2  2022-W8 600
2  2022-W8 600
2  2022-W8 600
2
  • Why are the final three rows of the output table the same? Commented Sep 21, 2022 at 13:23
  • @GregPavlik it was by mistaken added. correct the output. Commented Sep 21, 2022 at 14:02

1 Answer 1

2

Operating on string (YYYY-Wx) is not recommended, and it will be much easier if input is provided as first day of week (YYYY-MM-DD) and only transformed to YYYY-Wx for presentation.

Key ideas of script below:

  • transform week to date - column yw (DATEADD)
  • find next date (LEAD)
  • compute week difference (DATEDIFF)
  • create tally table (VALUES (0), (1),(2),(3),(4))
  • compute new dates
  • transform back to YYYY-Wx: (CONCAT)

Sample:

CREATE OR REPLACE TABLE tab(id INT, week TEXT, value INT )
AS
SELECT 1,  '2022-W1', 200 UNION 
SELECT 2,  '2022-W3', 500 UNION
SELECT 2,  '2022-W6', 600;

Query:

WITH cte AS (
  SELECT *, 
    DATEADD('week',REPLACE(week, LEFT(week,6)),
            DATE_FROM_PARTS(LEFT(week,4),1,1)) AS yw,
    DATEDIFF('week', YW, LEAD(yw) OVER(PARTITION BY id ORDER BY yw)) AS diff
  FROM tab
) 
SELECT cte.ID, 
   CONCAT(YEAR(DATEADD('week', s.num, cte.YW)), '-W',
          WEEK(DATEADD('week', s.num, cte.YW))) AS new_week, cte.value
FROM cte
JOIN (VALUES (0), (1),(2),(3),(4)) AS s(num)
  ON  s.num < cte.diff
  OR cte.diff IS NULL
ORDER BY cte.ID, cte.YW;

Output:

enter image description here

Warning: The computation YYYY-WW -> date -> back to week may not work across multiple years i.e, 2022-W52 -> 2023-W1. Testing such scenario is recommended. Ideally storing week as date.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.