Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/svn/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 用日期表填写日期间隔_Sql_Tsql_Join_Sql Server 2008 R2_Left Join - Fatal编程技术网

Sql 用日期表填写日期间隔

Sql 用日期表填写日期间隔,sql,tsql,join,sql-server-2008-r2,left-join,Sql,Tsql,Join,Sql Server 2008 R2,Left Join,我有两张桌子 带有客户和日期的订单表。 数据仓库中的日期维度表 orders表不包含给定月份中每个日期的活动,但我需要返回一个结果集,以填补date和customer之间的空白 例如,我需要这个: 问题是您需要所有日期的所有客户。当执行左外部联接时,customer字段将为NULL 以下内容通过交叉连接客户名称和日期来设置驱动程序表: SELECT driver.customer, driver.fulldate, o.amount FROM (select d.fulldate, cus

我有两张桌子

带有客户和日期的订单表。 数据仓库中的日期维度表

orders表不包含给定月份中每个日期的活动,但我需要返回一个结果集,以填补date和customer之间的空白

例如,我需要这个:


问题是您需要所有日期的所有客户。当执行左外部联接时,customer字段将为NULL

以下内容通过交叉连接客户名称和日期来设置驱动程序表:

SELECT driver.customer, driver.fulldate, o.amount 
FROM   (select d.fulldate, customer
        from datetable d cross join
             (select customer
              from orders
              where year(orderdate) in (2012)
             ) o
        where d.calendaryear IN ( 2012 )
       ) driver LEFT OUTER JOIN
       orders o 
       ON driver.fulldate = o.orderdate and
          driver.customer = o.customer;

请注意,此版本假定calendaryear与yearorderdate相同。

您可以使用递归CTE获取两个日期之间的所有日期,而不需要datetable:


下面是一个简单的方法:

SELECT  A.Customer,
        B.fulldate [Date],
        ISNULL(C.Amount,0) Amount
FROM (  SELECT  Customer, 
                MIN([Date]) MinDate,
                MAX([Date]) MaxDate
        FROM Orders
        GROUP BY Customer) A
LEFT JOIN DateTable B
    ON B.fulldate BETWEEN A.MinDate AND A.MaxDate
LEFT JOIN Orders C
    ON A.Customer = C.Customer 
    AND B.fulldate = C.[Date]

假设datetable包含一年中的每个日期,您可以使用一个简单的CTE来完成

WITH OrdersCustomerDateBorders AS
(
    SELECT CustomerID, MIN(fulldate) AS FirstOrderDate, MAX(fulldate) AS LastOrderDate
    FROM orders
    GROUP BY customer
)
select o.customer, d.fulldate, ISNULL(o.amount, 0) AS Amount
from orders o
INNER JOIN OrdersCustomerDateBorders OCDB ON OCDB.CustomerID = o.CustomerID
INNER JOIN datetable d ON  ON d.fulldate between OCDB.FirstOrderDate AND OCDB.LastOrderDate
WHERE d.calendaryear in (2012);

是否为每位客户填补空缺?那么,如果Cust1和Cust2在同一天有一个缺口,我们是否会按每个客户进行填补?您的示例数据不显示此信息—输出中有客户,但显示的日期只是orders表中的日期。我希望看到date表中的所有日期date表中没有订单日期的date应在该查询中显示customer null。如果日期范围变大,递归CTE可能会非常慢。如果两者都不存在,为什么不使用数字表、日历表或系统表呢?你可能会觉得有趣。谢谢你,这让我朝着正确的方向前进!
SELECT driver.customer, driver.fulldate, o.amount 
FROM   (select d.fulldate, customer
        from datetable d cross join
             (select customer
              from orders
              where year(orderdate) in (2012)
             ) o
        where d.calendaryear IN ( 2012 )
       ) driver LEFT OUTER JOIN
       orders o 
       ON driver.fulldate = o.orderdate and
          driver.customer = o.customer;
;WITH CTE_MinMax AS
(
    SELECT Customer, MIN(DATE) AS MinDate, MAX(DATE) AS MaxDate
    FROM dbo.orders
    GROUP BY Customer
)
,CTE_Dates AS
(
    SELECT Customer, MinDate AS Date
    FROM CTE_MinMax
    UNION ALL
    SELECT c.Customer, DATEADD(DD,1,Date) FROM CTE_Dates c
    INNER JOIN CTE_MinMax mm ON c.Customer = mm.Customer
    WHERE DATEADD(DD,1,Date) <= mm.MaxDate
)
SELECT c.* , COALESCE(o.Amount, 0)
FROM CTE_Dates c
LEFT JOIN Orders o ON c.Customer = o.Customer AND c.Date = o.Date
ORDER BY Customer, Date
OPTION (MAXRECURSION 0)
SELECT  A.Customer,
        B.fulldate [Date],
        ISNULL(C.Amount,0) Amount
FROM (  SELECT  Customer, 
                MIN([Date]) MinDate,
                MAX([Date]) MaxDate
        FROM Orders
        GROUP BY Customer) A
LEFT JOIN DateTable B
    ON B.fulldate BETWEEN A.MinDate AND A.MaxDate
LEFT JOIN Orders C
    ON A.Customer = C.Customer 
    AND B.fulldate = C.[Date]
WITH OrdersCustomerDateBorders AS
(
    SELECT CustomerID, MIN(fulldate) AS FirstOrderDate, MAX(fulldate) AS LastOrderDate
    FROM orders
    GROUP BY customer
)
select o.customer, d.fulldate, ISNULL(o.amount, 0) AS Amount
from orders o
INNER JOIN OrdersCustomerDateBorders OCDB ON OCDB.CustomerID = o.CustomerID
INNER JOIN datetable d ON  ON d.fulldate between OCDB.FirstOrderDate AND OCDB.LastOrderDate
WHERE d.calendaryear in (2012);