how to make a query for series of records ?

  • WeekNo FromDate ThruDate Period

    36 2016-08-29 2016-09-04 201609

    37 2016-09-05 2016-09-11 201609

    38 2016-09-12 2016-09-18 201609

    39 2016-09-19 2016-09-25 201609

    i want to make a series of record like this

    WeekNo Date Period

    36 2016-08-29 201609

    36 2016-08-30 201609

    36 2016-08-31 201609

    36 2016-09-01 201609

    36 2016-09-02 201609

    36 2016-09-03 201609

    36 2016-09-04 201609

    37 2016-09-05 201609

    37 2016-09-06 201609

    37 2016-09-07 201609

    37 2016-09-08 201609

    37 2016-09-09 201609

    37 2016-09-10 201609

    37 2016-09-11 201609

    38 2016-09-12 201609

    .... etc

    is it possible create a query using recursive cte ?

    i need a help from expert..

    thank u..

  • ok..

    i give u temporary table for u try..

    CREATE TABLE #tamp

    ( WeekNo INT, FromDate SMALLDATETIME, ThruDate SMALLDATETIME, Period VARCHAR(6) )

    INSERT INTO #tamp VALUES (36,'2016-08-29','2016-09-04','201609')

    INSERT INTO #tamp VALUES (37,'2016-09-05','2016-09-11','201609')

    INSERT INTO #tamp VALUES (38,'2016-09-12','2016-09-18','201609')

    INSERT INTO #tamp VALUES (39,'2016-09-19','2016-09-25','201609')

  • Recursive CTE can work, but it'll be slow and it's not a good solution.

    Better is to use a calendar table/numbers table. If you don't have one in the DB, create one (as a permanent table), they're very useful for a whole pile of things.

    Code in a few minutes...

    Gail Shaw
    Microsoft Certified Master: SQL Server, MVP, M.Sc (Comp Sci)
    SQL In The Wild: Discussions on DB performance with occasional diversions into recoverability

    We walk in the dark places no others will enter
    We stand on the bridge and no one may pass
  • actually i can loop datetime variable using while, and increment with 1 days through loop.

    but i wanna hear any idea which simplify the code..

    if u said using cte will getting worst performance, then i will wait for your code..

  • gentong.bocor (9/22/2016)


    ok..

    i give u temporary table for u try..

    CREATE TABLE #tamp

    ( WeekNo INT, FromDate SMALLDATETIME, ThruDate SMALLDATETIME, Period VARCHAR(6) )

    INSERT INTO #tamp VALUES (36,'2016-08-29','2016-09-04','201609')

    INSERT INTO #tamp VALUES (37,'2016-09-05','2016-09-11','201609')

    INSERT INTO #tamp VALUES (38,'2016-09-12','2016-09-18','201609')

    INSERT INTO #tamp VALUES (39,'2016-09-19','2016-09-25','201609')

    are you only going to be having one "period" or are you going to have a much lager data set that spans multiple periods/years?

    ________________________________________________________________
    you can lead a user to data....but you cannot make them think
    and remember....every day is a school day

  • J Livingston SQL (9/22/2016)


    gentong.bocor (9/22/2016)


    ok..

    i give u temporary table for u try..

    CREATE TABLE #tamp

    ( WeekNo INT, FromDate SMALLDATETIME, ThruDate SMALLDATETIME, Period VARCHAR(6) )

    INSERT INTO #tamp VALUES (36,'2016-08-29','2016-09-04','201609')

    INSERT INTO #tamp VALUES (37,'2016-09-05','2016-09-11','201609')

    INSERT INTO #tamp VALUES (38,'2016-09-12','2016-09-18','201609')

    INSERT INTO #tamp VALUES (39,'2016-09-19','2016-09-25','201609')

    are you only going to be having one "period" or are you going to have a much lager data set that spans multiple periods/years?

    basically, i want to make a function which supply only 1 parameter such as @year, then the query result number of week and date

    for example.. in september 2016, the first week is starting from 2016-08-29 up to 2016-09-04, the 2nd week is from 2016-09-05 up to 2016-09-11

    but i want the date become rows (not like my example FromDate & ThruDate) but just a series of date..

    i just call the function i.e dbo.fn_dayofweekcalendar(2016)

    then the result is like what i describe.

    thanks

  • gentong.bocor (9/22/2016)


    J Livingston SQL (9/22/2016)


    gentong.bocor (9/22/2016)


    ok..

    i give u temporary table for u try..

    CREATE TABLE #tamp

    ( WeekNo INT, FromDate SMALLDATETIME, ThruDate SMALLDATETIME, Period VARCHAR(6) )

    INSERT INTO #tamp VALUES (36,'2016-08-29','2016-09-04','201609')

    INSERT INTO #tamp VALUES (37,'2016-09-05','2016-09-11','201609')

    INSERT INTO #tamp VALUES (38,'2016-09-12','2016-09-18','201609')

    INSERT INTO #tamp VALUES (39,'2016-09-19','2016-09-25','201609')

    are you only going to be having one "period" or are you going to have a much lager data set that spans multiple periods/years?

    and what about periods...how are these calculated?

    12 per year / every 4 weeks or something else?

    basically, i want to make a function which supply only 1 parameter such as @year, then the query result number of week and date

    for example.. in september 2016, the first week is starting from 2016-08-29 up to 2016-09-04, the 2nd week is from 2016-09-05 up to 2016-09-11

    but i want the date become rows (not like my example FromDate & ThruDate) but just a series of date..

    i just call the function i.e dbo.fn_dayofweekcalendar(2016)

    then the result is like what i describe.

    thanks

    ________________________________________________________________
    you can lead a user to data....but you cannot make them think
    and remember....every day is a school day

  • The stuff you posted in the #tamp table, do you have that data at the start, or is it part of what you want to generate?

    Gail Shaw
    Microsoft Certified Master: SQL Server, MVP, M.Sc (Comp Sci)
    SQL In The Wild: Discussions on DB performance with occasional diversions into recoverability

    We walk in the dark places no others will enter
    We stand on the bridge and no one may pass
  • GilaMonster (9/22/2016)


    The stuff you posted in the #tamp table, do you have that data at the start, or is it part of what you want to generate?

    the #tamp table is the part of the result from my function..

    my function can produce the result like on #tamp table..

    but my code is not good enough.. i need your idea to make a function which result week number and series of date by supplying only the year

    select * from dbo.myfunction(2016) where weekno=1

    WeekNo Date Period

    1 2015-12-28 201601

    1 2015-12-29 201601

    1 2015-12-30 201601

    1 2015-12-31 201601

    1 2016-01-01 201601

    1 2016-01-02 201601

    1 2016-01-03 201601

    select * from dbo.myfunction(2016) where weekno=4

    WeekNo Date Period

    4 2016-01-18 201601

    4 2016-01-19 201601

    4 2016-01-20 201601

    4 2016-01-21 201601

    4 2016-01-22 201601

    4 2016-01-23 201601

    4 2016-01-24 201601

    hope u understand what i mean..

  • Quick inline calendar table example using the sample data posted previously on this thread.

    😎

    USE TEEST;

    GO

    SET NOCOUNT ON;

    IF OBJECT_ID(N'tempdb..#tamp') IS NOT NULL DROP TABLE #tamp;

    CREATE TABLE #tamp

    ( WeekNo INT, FromDate SMALLDATETIME, ThruDate SMALLDATETIME, Period VARCHAR(6) )

    INSERT INTO #tamp (WeekNo,FromDate,ThruDate,Period)

    VALUES (36,'2016-08-29','2016-09-04','201609')

    ,(37,'2016-09-05','2016-09-11','201609')

    ,(38,'2016-09-12','2016-09-18','201609')

    ,(39,'2016-09-19','2016-09-25','201609')

    ;

    CREATE NONCLUSTERED INDEX NCLIDX_#TAMP_FROMDATE_THRUDATE_INC_WEEKNO_PERIOD ON #tamp (FromDate ASC,ThruDate ASC) INCLUDE (WeekNo,Period);

    ;WITH T(N) AS (SELECT N FROM (VALUES (0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) AS X(N))

    ,BASE_CALENDAR_CONFIG AS

    (

    SELECT

    MIN(T.FromDate) AS FIRST_DATE

    ,DATEDIFF(DAY,MIN(T.FromDate),MAX(ThruDate)) AS NUM_DAYS

    FROM #tamp T

    )

    ,NUMS(N) AS (SELECT TOP((SELECT BCC.NUM_DAYS FROM BASE_CALENDAR_CONFIG BCC) + 1) ROW_NUMBER() OVER (ORDER BY (@@VERSION)) - 1 AS N

    FROM T T1,T T2,T T3,T T4,T T5,T T6,T T7,T T8,T T9)

    ,INLINE_CALENDAR AS

    (

    SELECT

    NM.N AS DATE_NO

    ,DATEADD(DAY,NM.N,BC.FIRST_DATE) AS DATE_VAL

    FROM BASE_CALENDAR_CONFIG BC

    CROSS APPLY NUMS NM

    )

    SELECT

    T.WeekNo

    ,INC.DATE_VAL

    ,T.Period

    FROM #tamp T

    CROSS APPLY INLINE_CALENDAR INC

    WHERE INC.DATE_VAL BETWEEN T.FromDate AND T.ThruDate;

    Output

    WeekNo DATE_VAL Period

    ----------- ----------------------- ------

    36 2016-08-29 00:00:00 201609

    36 2016-08-30 00:00:00 201609

    36 2016-08-31 00:00:00 201609

    36 2016-09-01 00:00:00 201609

    36 2016-09-02 00:00:00 201609

    36 2016-09-03 00:00:00 201609

    36 2016-09-04 00:00:00 201609

    37 2016-09-05 00:00:00 201609

    37 2016-09-06 00:00:00 201609

    37 2016-09-07 00:00:00 201609

    37 2016-09-08 00:00:00 201609

    37 2016-09-09 00:00:00 201609

    37 2016-09-10 00:00:00 201609

    37 2016-09-11 00:00:00 201609

    38 2016-09-12 00:00:00 201609

    38 2016-09-13 00:00:00 201609

    38 2016-09-14 00:00:00 201609

    38 2016-09-15 00:00:00 201609

    38 2016-09-16 00:00:00 201609

    38 2016-09-17 00:00:00 201609

    38 2016-09-18 00:00:00 201609

    39 2016-09-19 00:00:00 201609

    39 2016-09-20 00:00:00 201609

    39 2016-09-21 00:00:00 201609

    39 2016-09-22 00:00:00 201609

    39 2016-09-23 00:00:00 201609

    39 2016-09-24 00:00:00 201609

    39 2016-09-25 00:00:00 201609

  • Eirikur Eiriksson (9/22/2016)


    Quick inline calendar table example using the sample data posted previously on this thread.

    😎

    USE TEEST;

    GO

    SET NOCOUNT ON;

    IF OBJECT_ID(N'tempdb..#tamp') IS NOT NULL DROP TABLE #tamp;

    CREATE TABLE #tamp

    ( WeekNo INT, FromDate SMALLDATETIME, ThruDate SMALLDATETIME, Period VARCHAR(6) )

    INSERT INTO #tamp (WeekNo,FromDate,ThruDate,Period)

    VALUES (36,'2016-08-29','2016-09-04','201609')

    ,(37,'2016-09-05','2016-09-11','201609')

    ,(38,'2016-09-12','2016-09-18','201609')

    ,(39,'2016-09-19','2016-09-25','201609')

    ;

    CREATE NONCLUSTERED INDEX NCLIDX_#TAMP_FROMDATE_THRUDATE_INC_WEEKNO_PERIOD ON #tamp (FromDate ASC,ThruDate ASC) INCLUDE (WeekNo,Period);

    ;WITH T(N) AS (SELECT N FROM (VALUES (0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) AS X(N))

    ,BASE_CALENDAR_CONFIG AS

    (

    SELECT

    MIN(T.FromDate) AS FIRST_DATE

    ,DATEDIFF(DAY,MIN(T.FromDate),MAX(ThruDate)) AS NUM_DAYS

    FROM #tamp T

    )

    ,NUMS(N) AS (SELECT TOP((SELECT BCC.NUM_DAYS FROM BASE_CALENDAR_CONFIG BCC) + 1) ROW_NUMBER() OVER (ORDER BY (@@VERSION)) - 1 AS N

    FROM T T1,T T2,T T3,T T4,T T5,T T6,T T7,T T8,T T9)

    ,INLINE_CALENDAR AS

    (

    SELECT

    NM.N AS DATE_NO

    ,DATEADD(DAY,NM.N,BC.FIRST_DATE) AS DATE_VAL

    FROM BASE_CALENDAR_CONFIG BC

    CROSS APPLY NUMS NM

    )

    SELECT

    T.WeekNo

    ,INC.DATE_VAL

    ,T.Period

    FROM #tamp T

    CROSS APPLY INLINE_CALENDAR INC

    WHERE INC.DATE_VAL BETWEEN T.FromDate AND T.ThruDate;

    [/code]

    Output

    WeekNo DATE_VAL Period

    ----------- ----------------------- ------

    36 2016-08-29 00:00:00 201609

    36 2016-08-30 00:00:00 201609

    36 2016-08-31 00:00:00 201609

    36 2016-09-01 00:00:00 201609

    36 2016-09-02 00:00:00 201609

    36 2016-09-03 00:00:00 201609

    36 2016-09-04 00:00:00 201609

    37 2016-09-05 00:00:00 201609

    37 2016-09-06 00:00:00 201609

    37 2016-09-07 00:00:00 201609

    37 2016-09-08 00:00:00 201609

    37 2016-09-09 00:00:00 201609

    37 2016-09-10 00:00:00 201609

    37 2016-09-11 00:00:00 201609

    38 2016-09-12 00:00:00 201609

    38 2016-09-13 00:00:00 201609

    38 2016-09-14 00:00:00 201609

    38 2016-09-15 00:00:00 201609

    38 2016-09-16 00:00:00 201609

    38 2016-09-17 00:00:00 201609

    38 2016-09-18 00:00:00 201609

    39 2016-09-19 00:00:00 201609

    39 2016-09-20 00:00:00 201609

    39 2016-09-21 00:00:00 201609

    39 2016-09-22 00:00:00 201609

    39 2016-09-23 00:00:00 201609

    39 2016-09-24 00:00:00 201609

    39 2016-09-25 00:00:00 201609

    thanks Eirikur Eiriksson for your code,

    according to http://www.sqlservercentral.com/Forums/FindPost1819885.aspx

    can u make a function which result field weeknumber & date by @year as parameter ?

  • Everything needed was already in the code sample;-), here is a function that returns one year

    😎

    USE TEEST;

    GO

    SET NOCOUNT ON;

    GO

    CREATE FUNCTION dbo.ITVFN_CALENDAR_YEAR

    (

    @YEAR INT

    )

    RETURNS TABLE

    WITH SCHEMABINDING

    AS

    --------------------------------------------------------------------------------------

    -- INLINE CALENDAR RETURNING ONE YEAR

    -- 2016-09-22 Eirikur Eiriksson

    --------------------------------------------------------------------------------------

    RETURN

    WITH T(N) AS (SELECT N FROM (VALUES (0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) AS X(N))

    ,BASE_CALENDAR_CONFIG AS

    (

    SELECT

    DATEADD(YEAR,(@YEAR - 1900),0) AS FIRST_DATE

    ,DATEDIFF(DAY,DATEADD(YEAR,@YEAR - 1900,0),DATEADD(YEAR,(@YEAR - 1900) + 1,0)) AS NUM_DAYS

    )

    ,NUMS(N) AS (SELECT TOP((SELECT BCC.NUM_DAYS FROM BASE_CALENDAR_CONFIG BCC)) ROW_NUMBER() OVER (ORDER BY (@@VERSION)) - 1 AS N

    FROM T T1,T T2,T T3,T T4)

    ,INLINE_CALENDAR AS

    (

    SELECT

    NM.N AS DATE_NO

    ,CONVERT(DATE,DATEADD(DAY,NM.N,BC.FIRST_DATE),0) AS DATE_VAL

    FROM BASE_CALENDAR_CONFIG BC

    CROSS APPLY NUMS NM

    )

    SELECT

    CONVERT(INT,DATENAME(WEEK,INC.DATE_VAL),0) AS WEEK_NO

    ,INC.DATE_VAL AS DATE_VALUE

    ,(YEAR(INC.DATE_VAL) * 100)

    + CONVERT(INT,DATENAME(QUARTER,INC.DATE_VAL),0) AS PERIOD_NO

    FROM INLINE_CALENDAR INC;

    GO

    Usage

    DECLARE @YEAR INT = 2015;

    SELECT

    INC.WEEK_NO

    ,INC.DATE_VALUE

    ,INC.PERIOD_NO

    FROM dbo.ITVFN_CALENDAR_YEAR(@YEAR) AS INC

    WHERE INC.WEEK_NO = 32;

    Output

    WEEK_NO DATE_VALUE PERIOD_NO

    -------- ---------- -----------

    32 2015-08-02 201503

    32 2015-08-03 201503

    32 2015-08-04 201503

    32 2015-08-05 201503

    32 2015-08-06 201503

    32 2015-08-07 201503

    32 2015-08-08 201503

    Edit: removed implicit conversion

  • Eirikur Eiriksson (9/22/2016)


    Everything needed was already in the code sample;-), here is a function that returns one year

    😎

    USE TEEST;

    GO

    SET NOCOUNT ON;

    GO

    CREATE FUNCTION dbo.ITVFN_CALENDAR_YEAR

    (

    @YEAR INT

    )

    RETURNS TABLE

    WITH SCHEMABINDING

    AS

    --------------------------------------------------------------------------------------

    -- INLINE CALENDAR RETURNING ONE YEAR

    -- 2016-09-22 Eirikur Eiriksson

    --------------------------------------------------------------------------------------

    RETURN

    WITH T(N) AS (SELECT N FROM (VALUES (0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) AS X(N))

    ,BASE_CALENDAR_CONFIG AS

    (

    SELECT

    DATEADD(YEAR,(@YEAR - 1900),0) AS FIRST_DATE

    ,DATEDIFF(DAY,DATEADD(YEAR,@YEAR - 1900,0),DATEADD(YEAR,(@YEAR - 1900) + 1,0)) AS NUM_DAYS

    )

    ,NUMS(N) AS (SELECT TOP((SELECT BCC.NUM_DAYS FROM BASE_CALENDAR_CONFIG BCC)) ROW_NUMBER() OVER (ORDER BY (@@VERSION)) - 1 AS N

    FROM T T1,T T2,T T3,T T4)

    ,INLINE_CALENDAR AS

    (

    SELECT

    NM.N AS DATE_NO

    ,CONVERT(DATE,DATEADD(DAY,NM.N,BC.FIRST_DATE),0) AS DATE_VAL

    FROM BASE_CALENDAR_CONFIG BC

    CROSS APPLY NUMS NM

    )

    SELECT

    CONVERT(INT,DATENAME(WEEK,INC.DATE_VAL),0) AS WEEK_NO

    ,INC.DATE_VAL AS DATE_VALUE

    ,(YEAR(INC.DATE_VAL) * 100)

    + CONVERT(INT,DATENAME(QUARTER,INC.DATE_VAL),0) AS PERIOD_NO

    FROM INLINE_CALENDAR INC;

    GO

    Usage

    DECLARE @YEAR INT = 2015;

    SELECT

    INC.WEEK_NO

    ,INC.DATE_VALUE

    ,INC.PERIOD_NO

    FROM dbo.ITVFN_CALENDAR_YEAR(@YEAR) AS INC

    WHERE INC.WEEK_NO = 32;

    Output

    WEEK_NO DATE_VALUE PERIOD_NO

    -------- ---------- -----------

    32 2015-08-02 201503

    32 2015-08-03 201503

    32 2015-08-04 201503

    32 2015-08-05 201503

    32 2015-08-06 201503

    32 2015-08-07 201503

    32 2015-08-08 201503

    Edit: removed implicit conversion

    your function returning start date not the same as mine..

    let's say

    SELECT *

    FROM dbo.ITVFN_CALENDAR_YEAR(2016) AS INC

    WHERE INC.WEEK_NO = 32

    your function return start date with 2016-07-31, but mine is 2016-08-01

    2016-07-31 is part of week no. 31

    week no 31 is from 2016-07-25 up to 2016-07-31

    but yours is from 2016-07-24 up to 2016-07-30

    only different 1 days..

    which part should i modify ?

    thanks

  • @Eirikur Eiriksson

    i see, your code may get wrong result if called with week no. 1

    calling SELECT * FROM dbo.ITVFN_CALENDAR_YEAR(2016) AS INC

    WHERE INC.WEEK_NO = 1 may get 2 days, 2016-01-01 & 2016-01-02

    it should be from 2015-12-28 up to 2016-01-03

    here i give u my function :

    CREATE FUNCTION [dbo].[SplitPeriodByWeek] (@Year AS VARCHAR(4))

    RETURNS @RetStructure TABLE (BaseDate DATETIME, WeekNo INT, FromDate DATETIME, ThruDate DATETIME, Period VARCHAR(6))

    AS

    BEGIN

    DECLARE @BaseDatetmp DATETIME, @WKTmp INT, @WKSTmp INT, @WKETmp INT, @FromDate DATETIME, @ThruDate DATETIME

    SET @WKSTmp = 1

    SET @WKETmp = 52

    SET @WKTmp = @WKSTmp

    SET @BaseDatetmp = @Year+ '-01-01'

    IF UPPER(DATENAME(weekday, @BaseDatetmp)) = 'TUESDAY'

    SET @BaseDatetmp = DATEADD(DAY, -1, @BaseDatetmp)

    ELSE IF UPPER(DATENAME(weekday, @BaseDatetmp)) = 'WEDNESDAY'

    SET @BaseDatetmp = DATEADD(DAY, -2, @BaseDatetmp)

    ELSE IF UPPER(DATENAME(weekday, @BaseDatetmp)) = 'THURSDAY'

    SET @BaseDatetmp = DATEADD(DAY, -3, @BaseDatetmp)

    ELSE IF UPPER(DATENAME(weekday, @BaseDatetmp)) = 'FRIDAY'

    SET @BaseDatetmp = DATEADD(DAY, -4, @BaseDatetmp)

    ELSE IF UPPER(DATENAME(weekday, @BaseDatetmp)) = 'SATURDAY'

    SET @BaseDatetmp = DATEADD(DAY, -5, @BaseDatetmp)

    ELSE IF UPPER(DATENAME(weekday, @BaseDatetmp)) = 'SUNDAY'

    SET @BaseDatetmp = DATEADD(DAY, -6, @BaseDatetmp)

    WHILE @WKTmp <= @WKETmp

    BEGIN

    INSERT INTO @RetStructure

    SELECT @BaseDatetmp, @WKTmp, DATEADD(DAY, 7 * (@WKTmp - 1), @BaseDatetmp), DATEADD(DAY, -1, DATEADD(DAY, 7 * @WKTmp, @BaseDatetmp)), ''

    SET @WKTmp = @WKTmp + 1

    END

    UPDATE @RetStructure SET period=CONVERT(VARCHAR(6),thrudate,112)

    RETURN

    END

  • anyone ???

Viewing 15 posts - 1 through 14 (of 14 total)

You must be logged in to reply to this topic. Login to reply