从火鸟给定范围内选择日期的列表

问题描述 投票:1回答:1

我设计一个返回由于在未来一周的PurchaseOrder的报告。

我已经低于收益增加查询PurchaseOrder由于特定CommodityAmountDue及其DeliveryDate

显然,它只返回那些在表PO_Dates。我要的是还包括日期,在没有订单的预期,即空的那些细胞。

对我来说,一个可能性是左连接与设置在日期列未来一周的日期的数据集,这将最终使结果无效在没有采购订单的预期。

在火鸟,我不知道如何选择为期一周的日期列表,然后在连接使用。

SELECT
    PURCHASE_ORDER_DET.COMMODITYID AS COM_ID,
    PURCHASE_ORDER_DET.DELIVERYDATE + CAST ('29.12.1899' AS DATE) as DLV_DATE,
    SUM(PURCHASE_ORDER_DET.REQQUANTITY) as DLV_DUE
FROM
    PURCHASE_ORDER_DET
LEFT JOIN PURCHASE_ORDER_HDR on PURCHASE_ORDER_HDR.POH_ID = 
PURCHASE_ORDER_DET.POH_ID
WHERE 
    PURCHASE_ORDER_DET.COMMODITYID = 1
    AND PURCHASE_ORDER_HDR.STATUS in (0,1,2)
    AND PURCHASE_ORDER_DET.DELIVERYDATE + CAST ('30.12.1899' AS TIMESTAMP) >= '3.01.2019'
    AND PURCHASE_ORDER_DET.DELIVERYDATE + CAST ('30.12.1899' AS TIMESTAMP) <= '9.01.2019'
    AND PURCHASE_ORDER_DET.DELETED is NULL
Group by 
    PURCHASE_ORDER_DET.COMMODITYID,
    PURCHASE_ORDER_DET.DELIVERYDATE

数据集

COM_ID    DLV_DATE       DLV_DUE    
1         3.01.2019     50.000000
1         5.01.2019     10.000000

预期

COM_ID    DLV_DATE       DLV_DUE    
1         3.01.2019     50.000000
1         4.01.2019     null
1         5.01.2019     10.000000
1         6.01.2019     null
1         7.01.2019     null
1         8.01.2019     null
1         9.01.2019     null
sql firebird gaps-and-islands
1个回答
0
投票

忽略你的奇使用的数据类型*的,有几个可能的解决方案:

  1. 使用包含日期的“日历”表,右连接到该表(或左从该表中加入)。当然的缺点是具有填充此表(但这是一个一次性的成本)。
  2. 使用可选的存储过程来产生一日期范围,并加入上。
  3. 生成在查询自身的递归公用表表达式的范围内

选项1是不言自明。

选项2看起来是这样的:

CREATE OR ALTER PROCEDURE date_range(startdate date, enddate date)
  RETURNS (dateval date)
AS
BEGIN
    dateval = startdate;
    while (dateval <= enddate) do
    BEGIN
       suspend;
       dateval = dateval + 1;
    END
END

然后在您的查询像这样使用:

select date_range.dateval, ...
from date_range(date'2019-01-03', date'2019-01-09') -- use date_range(?, ?) for parameters
left join ...
  on date_range.dateval = ...

方案3看起来是这样的:

WITH RECURSIVE date_range AS (
    SELECT date'2019-01-03' dateval  -- start date, use cast(? as date) if you need a parameter
    FROM rdb$database
    UNION ALL 
    SELECT dateval + 1
    FROM date_range
    WHERE dateval < date'2019-01-09' -- end date use ? if you need a parameter
)
SELECT *
FROM date_range
LEFT JOIN ... 
  ON date_range.dateval = ... 

递归公用表表达式有1024最大递归深度,这意味着它不适合,如果你需要一个跨度超过1024天广。


*:我建议你开始使用的,而不是什么样子,因为30-12-1899天数DATE。这避免了不得不做的尴尬计算像你现在要做的。如果你确实需要的天数者,那么你可以使用例如或datediff(DAY FROM date'1899-12-30' TO somedatevalue)somedatevalue - date'1899-12-30'从日期转换为数值。

© www.soinside.com 2019 - 2024. All rights reserved.