与客户和日期对应的结果

时间:2014-06-25 15:17:41

标签: sql sql-server sql-server-2008

即使两个日期之间没有订单,我如何获得所有日期?

样本表

OrderID  | Date      | CusID
33942    | 6-21-2014 | 6005
34059    | 6-20-2014 | 4003
53333    | 6-23-2014 | 6005
59234    | 6-23-2014 | 4003

我怎么能得到这个结果?

CusID   | Date      | OrderID |
4003    | 6-20-2014 | 34059   | 
4003    | 6-21-2014 | null    | 
4003    | 6-22-2014 | null    | 
4003    | 6-23-2014 | 59234   | 
6005    | 6-20-2014 | null    | 
6005    | 6-21-2014 | 33942   | 
6005    | 6-22-2014 | null    | 
6005    | 6-23-2014 | 53333   | 

这是我到目前为止所做的。

我创建了一个日历表

CREATE TABLE #Calendar
(
    [CalendarDate] DATETIME
)

DECLARE @StartDate DATETIME
DECLARE @EndDate DATETIME
SET @EndDate = GETDATE()
SET @StartDate = DATEADD(Year, -1, @EndDate)


WHILE @StartDate <= @EndDate
      BEGIN
             INSERT INTO #Calendar
             (
                   CalendarDate
             )
             SELECT
                   @StartDate

             SET @StartDate = DATEADD(dd, 1, @StartDate)
      END 

然后这是我的查询,但没有给我所需的结果

Select t.CusID, c.CalendarDate, t.OrderID 
From #Calendar c 
left outer join
#temp t
ON
CONVERT(VARCHAR(10), c.CalendarDate, 112) = CONVERT(VARCHAR(10), t.Date, 112)
Where c.CalendarDate Between '6-20-2014' and '6-23-2014'
Order By t.Name

2 个答案:

答案 0 :(得分:1)

首先,您的日历表已损坏。您正在使用日期时间戳,并捕获表中的当前时间戳。最好写出正确的数据,而不是稍后处理。

对此进行两项修复,使用DATE格式或convert您的日期来删除时间戳。我选择了后者。

从那里,您缩小到被查询的天数,以及当时的客户数量,并生成这两个子集的交叉连接。

DECLARE @ORDER TABLE (ORDERID INT, ordDATE DATETIME, CUSID INT)
INSERT INTO @ORDER (ORDERID, ordDATE, CUSID)
VALUES (33942,'6-21-2014', 6005), 
       (34059,'6-20-2014',4003), 
       (53333,'6-23-2014',6005), 
       (59234,'6-23-2014',4003)

declare @Calendar table ([CalendarDate] DATETIME)

DECLARE @StartDate DATETIME
DECLARE @EndDate DATETIME
SET @EndDate = GETDATE()
SET @StartDate = DATEADD(Year, -1, @EndDate)

WHILE @StartDate <= @EndDate
      BEGIN
             INSERT INTO @Calendar
             (
                   CalendarDate
             )
             SELECT
                   CONVERT(DATETIME,FLOOR(CONVERT(FLOAT, @StartDate)))

             SET @StartDate = DATEADD(dd, 1, @StartDate)
      END 

; with dates as
(
   SELECT DISTINCT CalendarDate
   FROM @Calendar
   WHERE CalendarDate BETWEEN '2014-06-20' AND '2014-06-23'
),
orders as
(
    SELECT DISTINCT CUSID
    FROM @ORDER
    WHERE ordDATE BETWEEN '2014-06-20' AND '2014-06-23'
),
cp AS
(
    SELECT *
    FROM dates
    CROSS JOIN orders
)

SELECT cp.CUSID, cp.CalendarDate, O.ORDERID
FROM CP
LEFT OUTER JOIN @ORDER O 
   ON cp.CalendarDate = O.ordDATE 
   AND cp.CUSID = O.CUSID

如果您愿意,可以将WHERE子句移到CTE之外并进入最终的select语句,但生成的cp表会大得多,而且在大数据集上会更慢

答案 1 :(得分:0)

创建日期和客户的笛卡尔积,然后加入

with cte as 
(
    select caldate, custid
    from calendar, customers
)
select *
from cte
left join temp o 
on cte.custid = o.custid
and cast(caldate as date) = cast(orderdate as date)
where caldate between '20140620' and '20140623'