简体   繁体   中英

Split single row into multiple rows based on week of the month in date

I have a table like this

Id      Valid_From    Valid_To
9744    24/06/2019    07/07/2019
9745    12/08/2019    31/12/9999

I would like to split this table into multiple rows based on the week like this by joining to the date table

Id      Valid_from   Valid_To    Month       Week
9744    24/06/2019   07/07/2019  June        4
9744    24/06/2019   07/07/2019  July        1
9744    24/06/2019   07/07/2019  July        2
9745    12/08/2019   31/12/9999  August      2
9745    12/08/2019   31/12/9999  August      3
9745    12/08/2019   31/12/9999  August      4

In this case there will be 3 rows as the valid from and valid two falls between these 3 weeks for ID - 9744

For ID - 9745 the Valid_to date is infinity so we need to just take all the week in the current month from the valid_from date

I then just need to append the output with Month and the Week number

Can someone help me to write a query to have this output?

Thanks

You mention a "date" table. If you have one then you can use a join like this:

select distinct t.id, valid_from, t.valid_to, d.month, d.week
from yourtable t join
     date d
     on d.date >= t.valid_from and
        d.date <= t.valid_to;

If I understand your question right, you need to list all month names and week numbers of these months' existing between valid_from and valid_to dates. I did it by following query:

SELECT 
  Q.ID, 
  Q.VALID_FROM,
  Q.VALID_TO,
  Q.MONTH_NAME,
  WEEK_NUMBER
FROM
(
  SELECT
    CEIL((Q.DATES_BETWEEN_INTERVAL - FIRST_DAY_OF_MONTH + 1) / 7) WEEK_NUMBER,
    TO_CHAR(Q.DATES_BETWEEN_INTERVAL, 'MONTH', 'NLS_DATE_LANGUAGE = American') MONTH_NAME,
    Q.* 
  FROM
  (
    SELECT  
      LEVEL + S.VALID_FROM DATES_BETWEEN_INTERVAL,
      TRUNC(LEVEL + S.VALID_FROM, 'MONTH') FIRST_DAY_OF_MONTH,
      S.* FROM
    (
      SELECT T.*, 
        (CASE WHEN EXTRACT(YEAR FROM T.VALID_TO) = 9999 THEN LAST_DAY(T.VALID_FROM) ELSE T.VALID_TO END) - T.VALID_FROM DAYS_COUNT
      FROM AAA_TABLE T
    ) S
    CONNECT BY LEVEL <= S.DAYS_COUNT
  ) Q
) Q
GROUP BY 
  Q.ID, 
  Q.VALID_FROM,
  Q.VALID_TO,
  Q.MONTH_NAME,
  WEEK_NUMBER
ORDER BY
  Q.ID, 
  Q.VALID_FROM,
  Q.VALID_TO,
  Q.MONTH_NAME,
  WEEK_NUMBER;

But there must be 5th week if the date greater than 28th day of month. Hope this will help you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM