it-swarm-id.com

Buat Tanggal antara rentang tanggal

Saya perlu mengisi tabel yang akan menyimpan rentang tanggal antara 2 tanggal yang diberikan: 09/01/11 - 10/10/11

Jadi dalam hal ini tabel akan mulai dari 09/01/11 dan menyimpan setiap hari sampai dengan 10/10/11 Saya bertanya-tanya apakah ada cara yang licin untuk melakukan ini di SQL Server - Saya saat ini menggunakan SQL Server 2008. Terima kasih

29
Nate Pet

Mudah menggunakan SQL 2005+; lebih mudah jika Anda memiliki angka atau tabel penghitungan. Saya memalsukannya di bawah ini:

DECLARE @StartDate DATE = '20110901'
  , @EndDate DATE = '20111001'

SELECT  DATEADD(DAY, nbr - 1, @StartDate)
FROM    ( SELECT    ROW_NUMBER() OVER ( ORDER BY c.object_id ) AS Nbr
          FROM      sys.columns c
        ) nbrs
WHERE   nbr - 1 <= DATEDIFF(DAY, @StartDate, @EndDate)

Jika Anda memiliki tabel penghitungan, ganti subquery dengan tabel. Tidak ada rekursi.

29
Stuart Ainsworth

Coba ini jika Anda menggunakan SQL Server 2005 atau yang lebih baru:

WITH Dates AS (
        SELECT
         [Date] = CONVERT(DATETIME,'09/01/2011')
        UNION ALL SELECT
         [Date] = DATEADD(DAY, 1, [Date])
        FROM
         Dates
        WHERE
         Date < '10/10/2011'
) SELECT
 [Date]
FROM
 Dates
 OPTION (MAXRECURSION 45)

Contoh bagus dari hal-hal keren yang dapat Anda lakukan dengan CTE. 

33
Abe Miessler

- Deklarasi

DECLARE @dates TABLE(dt datetime)    
DECLARE @dateFrom datetime
DECLARE @dateTo datetime

SET @dateFrom = '2001/01/01'
SET @dateTo = '2001/01/12'

- Permintaan:

WHILE(@dateFrom < @dateTo)
BEGIN
   SELECT @dateFrom = DATEADD(day, 1,@dateFrom)
   INSERT INTO @dates 
   SELECT @dateFrom
END

- Output

SELECT * FROM @dates
9
sll

Berikut adalah solusi yang tidak memerlukan rekursi, dan pada saat yang sama, fungsi bernilai tabel ini dapat digunakan kembali di banyak pertanyaan tanpa perlu mengulangi deklarasi variabel boilerplate lagi. Ini adalah satu-satunya alternatif, bagi mereka yang tidak menginginkan rekursi.

Buat fungsi sederhana ini:

CREATE FUNCTION [dbo].[GenerateDateRange]
(@StartDate AS DATE,
 @EndDate AS   DATE,
 @Interval AS  INT
)
RETURNS @Dates TABLE(DateValue DATE)
AS
BEGIN
    DECLARE @CUR_DATE DATE
    SET @CUR_DATE = @StartDate
    WHILE @CUR_DATE <= @EndDate BEGIN
        INSERT INTO @Dates VALUES(@CUR_DATE)
        SET @CUR_DATE = DATEADD(DAY, @Interval, @CUR_DATE)
    END
    RETURN;
END;

Dan kemudian pilih dengan:

select *
from dbo.GenerateDateRange('2017-01-03', '2017-12-01', 1)
2
sken130

Gunakan fungsi F_TABLE_DATE MVJ, ini benar-benar luar biasa:

http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=61519

Setelah Anda menerapkan ini, cukup lewati tanggal mulai dan berakhir dan Anda dapat memasukkan semua tanggal di antara.

2
JonH

Menggunakan jawaban @Abe Miesler, untuk kenyamanan orang lain saya membuatnya menjadi TVF untuk SQL Server 2008 dan seterusnya. Mungkin membantu orang lain - saya harus menemukan cara untuk memasukkan CTE ke dalam TVF!

    --Generate a range of dates with interval option, courtesy of Abe Miessler for the core query here!
ALTER FUNCTION [dbo].[DateRange]
(@startDate AS DATE,
 @EndDate AS   DATE,
 @interval AS  INT
)
RETURNS @Dates TABLE(dateValue DATE)
AS
     BEGIN
         WITH Dates
              AS (
              SELECT [Date] = CONVERT( DATETIME, @startDate)
              UNION ALL
              SELECT [Date] = DATEADD(DAY, ISNULL(@interval, 1), [Date])
              FROM Dates
              WHERE Date < @EndDate)
              INSERT INTO @Dates
                     SELECT [Date]
                     FROM Dates
                     OPTION(MAXRECURSION 900);
         RETURN;
     END;
0
Declare @StartDate datetime = '2015-01-01'
Declare @EndDate datetime = '2016-12-01'
declare @DaysInMonth int
declare @tempDateRange Table
(
DateFrom datetime,
DateThru datetime
);

While @StartDate<[email protected]
begin
    SET @DaysInMonth=DAY(DATEADD(DD,-1,DATEADD(MM,DATEDIFF(MM,-1,@StartDate),0)))

    IF DAY(@StartDate)=1 
        SET @EndDate=DATEADD(DAY,14,@StartDate)
    ELSE IF DAY(@StartDate)=16 AND @DaysInMonth=30
        SET @EndDate=DATEADD(DAY,14,@StartDate)
    ELSE IF DAY(@StartDate)=16 AND @DaysInMonth=31
        SET @EndDate=DATEADD(DAY,15,@StartDate)
    ELSE IF DAY(@StartDate)=16 AND @DaysInMonth=28
        SET @EndDate=DATEADD(DAY,12,@StartDate)
    ELSE IF DAY(@StartDate)=16 AND @DaysInMonth=29
        SET @EndDate=DATEADD(DAY,13,@StartDate)

    INSERT INTO @tempDateRange (DateFrom,DateThru)
    VALUES 
     (
        @StartDate,
        @EndDate
     )

    SET @StartDate=DATEADD(DAY,1,@EndDate)

    IF @EndDate< '2016-12-31'
     IF DAY(@StartDate)=1 
        SET @EndDate=DATEADD(DAY,14,@StartDate)
     ELSE IF DAY(@StartDate)=16 AND @DaysInMonth=30
        SET @EndDate=DATEADD(DAY,14,@StartDate)
     ELSE IF DAY(@StartDate)=16 AND @DaysInMonth=31
        SET @EndDate=DATEADD(DAY,15,@StartDate)
     ELSE IF DAY(@StartDate)=16 AND @DaysInMonth=28
        SET @EndDate=DATEADD(DAY,12,@StartDate)
     ELSE IF DAY(@StartDate)=16 AND @DaysInMonth=29
        SET @EndDate=DATEADD(DAY,13,@StartDate)
end ;

select * from @tempDateRange

+++++++++++++++++++++++++++++
Result:
DateFrom |DateThru
0
SanH

Jika karena alasan tertentu Anda tidak bisa variabel declare, seperti ketika menggunakan diturunkan tabel in Looker , Anda bisa seperti ini:

select
  dateadd(day, nbr - 1, convert(date, '2017-01-01')) as d
from (
  select row_number() over (order by c.object_id) as nbr from sys.columns c
) nbrs
where
  nbr - 1 <= datediff(
    day,
    convert(date, '2017-01-01'),
    convert(date, '2018-12-31')
  )

Ngomong-ngomong, beginilah tampilan tampilan seri Anda di LookerML:

view: date_series {
  derived_table: {
    sql:
      select
        dateadd(day, nbr - 1, convert(date, '2017-01-01')) as d
      from (
        select row_number() over (order by c.object_id) as nbr from sys.columns c
      ) nbrs
      where
        nbr - 1 <= datediff(day, convert(date, '2017-01-01'), convert(date, '2018-12-31')) ;;
  }

  dimension: date {
    primary_key: yes
    type: date
    sql: ${TABLE}.d ;;
  }
}
0
Lars Blumberg