Creating a date table for multiple primary keys between a specified open and close date for each primary key

问题: Good day, I have been wracking my brain for the past few hours to build a table that looks like this: I have about 33 000 entries that have their own opening and clo...

问题:

Good day,

I have been wracking my brain for the past few hours to build a table that looks like this:

enter image description here

I have about 33 000 entries that have their own opening and closing dates. I am trying to build a table that puts each of the dates (including the opening and closing dates) in a single row per entry (JOURNAL_NO) below each other in SQL Server Management Studio.

I need to run a check on each day for each entry and I have tried to build the table by making use of my primary table and a calendar table that I created. Please refer to the code below (I have also included the calendar code below this):

Code I'm trying to get working:

DECLARE @START_DATE date = '2014-01-01',
        @END_DATE date = '2018-12-31'
WHILE @START_DATE <= @END_DATE
BEGIN
    SET @START_DATE = DATEADD(DAY, ROW_NUMBER() OVER(ORDER BY N) - 1, @START_DATE)

    SELECT LO_MASTER.JOURAL_NO, --(33000 entries)
            LO_MASTER.START_DATE, -- each entry has a different opening date 
            CAL.DATE -- date in calendar table
            CAL.DAY AS DATEPART(DAY,[DATE]),
            CAL.MONTH AS DATEPART(MONTH,[DATE]),
            CAL.YEAR AS DATEPART(YEAR,[DATE]), -- these will be the date parts between the OPEN_DATE & CLOSE_DATE for each account
            LO_MASTER.END_DATE -- each entry has a different closing date
    FROM [dbo.][F1_master] as LO_MASTER
         inner join CALENDAR_TABLE as CAL LO_MASTER.DATE = CAL.DATE
    WHERE CAL.DATE between LO_MASTER.START_DATE and LO_MASTER.END_DATE -- range where the fields from table b need to be populated for each account

END

Table definition:

USE [master]
GO

/****** Object:  Table [dbo].[dummy_data]    Script Date: 11/02/2019 07:31:59 PM ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[dummy_data](
    [JOURNAL_NO] [int] NULL,
    [START_DATE] [date] NULL,
    [END_DATE] [date] NULL,
    [DURATION_ON_BOOK] [int] NULL
) ON [PRIMARY]
GO

Sample data:

JOURNAL_NO  START_DATE  END_DATE    DURATION_ON_BOOK
101388  15/01/2014  01/01/2017  35
101499  14/01/2014  21/01/2017  36
101502  17/01/2014  17/02/2017  53
101876  06/01/2014  30/09/2017  35
101877  06/01/2014  24/01/2018  60
101878  07/01/2014  28/02/2018  60
101879  07/01/2014  19/01/2017  50
101881  07/01/2014  16/04/2018  58
101882  07/01/2014  13/11/2018  58
101883  08/01/2014  17/11/2016  59
101884  13/01/2014  26/06/2018  60
101886  13/01/2014  20/12/2016  59
101887  13/01/2014  13/12/2016  60
101888  13/01/2014  11/09/2017  43
101889  14/01/2014  07/12/2017  68
101890  14/01/2014  02/01/2018  58
101892  15/01/2014  21/02/2017  38
101893  17/01/2014  15/09/2017  64
101894  21/01/2014  02/02/2017  40
101896  21/01/2014  09/05/2016  38
101904  27/01/2014  21/12/2016  69
101906  27/01/2014  11/11/2016  36
101966  07/01/2014  10/03/2017  36
101967  07/01/2014  09/07/2018  40
102073  07/01/2014  15/09/2016  60
102074  13/01/2014  20/06/2017  40
102076  14/01/2014  15/06/2016  40
102077  15/01/2014  01/12/2016  60
102079  17/01/2014  12/10/2016  40
102081  21/01/2014  20/04/2017  40
102082  23/01/2014  14/02/2017  38
102234  02/01/2014  20/09/2017  46
102236  08/01/2014  05/05/2017  36
102237  15/01/2014  23/08/2017  68
102240  21/01/2014  27/02/2018  50
102241  21/01/2014  25/08/2016  37
102253  06/01/2014  26/10/2016  27
102254  07/01/2014  17/11/2016  61
102255  07/01/2014  26/04/2017  38
102256  10/01/2014  11/10/2017  42
102258  13/01/2014  18/05/2017  26
102263  17/01/2014  29/11/2018  74
102265  20/01/2014  31/10/2016  31
102372  06/01/2014  25/04/2017  35
102463  09/01/2014  25/08/2017  69
102464  09/01/2014  01/07/2016  26
102465  15/01/2014  24/12/2016  36
102530  06/01/2014  24/12/2017  48
102531  07/01/2014  28/08/2017  76
102532  09/01/2014  21/06/2017  39

Could anyone please assist me? I haven't been coding that long and my troubleshoot attempts aren't providing any correct solutions. It would be greatly appreciated.

Thank you.


回答1:

Using a tally table this is pretty simple. I keep one on my system as a view that is lightning fast because it doesn't need any disc I/O at all. It look amazingly similar to what you had posted initially.

create View [dbo].[cteTally] as

WITH
    E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
    E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
    E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
    cteTally(N) AS 
    (
        SELECT  ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
    )
select N from cteTally
GO

Next we need some sample data. I stripped this down to just a couple of journals to demonstrate.

declare @dummy_data table
(
    JOURNAL_NO int
    , START_DATE datetime
    , END_DATE datetime
    , DURATION_ON_BOOK int
)

insert @dummy_data values
(101388, '20140115', '20170101', 35)
, (101499, '20160114', '20170121', 36)

Now we just need to leverage the power of a tally table with your data. This is what your query might look like. No need for loops, just some basic date math.

select *
    , EachDay = dateadd(day, t.N - 1, d.Start_Date)
    , MyDay = t.N
    , MyMonth = datediff(month, d.Start_DATE, dateadd(day, t.N - 1, d.Start_Date)) + 1
    , MyYear = datepart(year, dateadd(day, t.N - 1, d.Start_Date))
from @dummy_data d
join cteTally t on t.N <= datediff(day, d.START_DATE, d.END_DATE) + 1
  • 发表于 2019-02-15 00:16
  • 阅读 ( 196 )
  • 分类:网络文章

条评论

请先 登录 后评论
不写代码的码农
小编

篇文章

作家榜 »

  1. 小编 文章
返回顶部
部分文章转自于网络,若有侵权请联系我们删除