【问题标题】:List all Dates between two Date columns of a table列出表的两个日期列之间的所有日期
【发布时间】:2011-10-19 03:58:29
【问题描述】:

我的表 PRODUCT 有 3 列:

Product_ID
INTRODUCED_DATE
WITHDRAWAL_DATE

我需要从该表中创建一个派生表PRODUCT_ALL_DATES,其中列出了产品处于活动状态的所有日期。日期范围是INTRODUCED_DATE(开始日期)和WITHDRAWAL_DATE(结束日期)

如何在 SQL Server 中实现这一点?我已在附图中指出了示例输出:

谢谢!

【问题讨论】:

标签: sql sql-server date


【解决方案1】:
declare @dateh table(ind int identity(1,1),date1 smalldatetime,date2 smalldatetime)

insert into @dateh select '1/1/2011','1/15/2011'

select * from @dateh

;with T as
(
    select date1,date2 from @dateh as d
    union all
    select dateadd(dd,1,date1),date2 From T 
    where  dateadd(dd,1,date1)<= date2
)
Select date1 from T

【讨论】:

  • 如果递归执行超过 100 次(更大的日期范围),它将终止。您需要在末尾添加 OPTION (MAXRECURSION 0) 才能在更大的日期范围内正确执行。
【解决方案2】:

我可以想到两种方法来实现这一点

  1. 编写存储过程并循环填充第二个表
  2. 用另一种语言编写程序来执行此操作。

显而易见的问题是您为什么要这样做?当前形式的数据无法解决的问题是什么

【讨论】:

    【解决方案3】:

    这是您的问题的答案, 我通过使用光标尝试了这个。它工作正常。

        CREATE TABLE product
    (
    product_id int
    ,INTRODUCED_DATE DATETIME
    ,WITHDRAWAL_DATE DATETIME
    )
    
    INSERT INTO product VALUES (100,'01-01-2011','01-05-2011')
    INSERT INTO product VALUES (200,'05-30-2011','06-05-2011')
    
    CREATE TABLE PRODUCT_ALL_DATES
    (
    product_id int
    ,Dates_Active DATETIME
    )
    
    DECLARE @product int
    ,@Introduct_Date DATETIME
    ,@Withdrawal_date DATETIME
    ,@Dates_Active DATETIME
    
    DECLARE pointer_cur CURSOR FAST_FORWARD
    FOR
    SELECT * FROM product a
    
    OPEN pointer_cur
    
    FETCH NEXT FROM pointer_cur
    INTO @Product,@Introduct_Date,@Withdrawal_date
    
    WHILE(@@FETCH_STATUS=0)
    BEGIN
    
        WHILE(@Introduct_Date<=@Withdrawal_date)
        BEGIN
            SET @Dates_Active=@Introduct_Date
    
            INSERT INTO PRODUCT_ALL_DATES
            SELECT @product,@Dates_Active
    
            SELECT @Introduct_Date=dateadd(day,1,@Introduct_Date)
    
        END
    
    FETCH NEXT FROM POINTER_CUR
    INTO @Product,@Introduct_Date,@Withdrawal_date
    
    END
    
    CLOSE POINTER_CUR
    DEALLOCATE POINTER_CUR
    
    SELECT * FROM PRODUCT_ALL_DATES 
    

    【讨论】:

      【解决方案4】:

      根据日期的总范围,这应该有效。如果总体日期范围较大,您可能需要调整 MAX 递归。

      ;WITH DaysCTE( Date ) as
      (
          SELECT MIN(INTRODUCED_DATE) AS Date FROM PRODUCT
              UNION ALL
          SELECT DATEADD(day, 1, Date) 
              FROM DaysCTE
              where Date < (SELECT MAX(@WITHDRAWAL_DATE) FROM PRODUCT)
      )
      
      SELECT
         PRODUCT_ID,
         DaysCTE.Date
      FROM
         PRODUCT
      INNER JOIN DaysCTE
       ON DaysCTE.Date >= PRODUCT.INTRODUCED_DATE
          AND DaysCTE.DATE <= PRODUCT.WITHDRAWAL_DATE
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-07-05
        • 1970-01-01
        • 2022-01-04
        • 1970-01-01
        • 2018-04-30
        • 2023-03-30
        • 2010-10-05
        • 1970-01-01
        相关资源
        最近更新 更多