减去涉及多个联接的日期

时间:2015-01-07 16:09:24

标签: sql-server

我希望有人可以帮助我。

我有以下5个表:

tblCustomer

CustomerID   CustomerName   
 -------     ------------
   1         ABC Bank     
   2         Chase Bank      

tblOrderType

OrderTypeID    OrderTypeName   
 ----------    ------------
   1           Assignment     
   2           LienRelease  

tblActivity

ActivityID        ActivityName   
 ----------       ------------
   1              Received     
   2              Keyed
   3              Printed
   4              Delivered To Customer

tblOrder

OrderID        CustomerID      OrderTypeID   LoanNumber
 ----------    ------------    -----------   ----------
   1           1                1            45584565
   2           1                1            45566856
   3           1                1            45565584
   4           1                1            45588545

tblOrderActivity

OrderID        ActivityID    ActivityDate
 ----------    -----------   ----------
   1           1             2007-04-16 8:34:00 AM
   1           2             2007-04-16 9:22:00 AM  
   1           3             2007-04-16 9:51:00 AM 
   1           4             2007-04-16 4:14:00 PM  
   2           1             2007-04-16 8:34:00 AM
   2           3             2014-12-16 10:33:09 AM
   3           1             2007-04-16 8:34:00 AM
   3           2             2007-04-16 9:22:00 AM
   3           3             2007-04-16 9:51:00 AM
   3           4             2007-04-16 4:14:00 PM
   4           1             2007-04-16 8:34:00 AM
   4           2             2007-04-16 9:22:00 AM
   4           3             2007-04-16 9:51:00 AM 

为保护目的,信息已被更改。所以说我需要能够按客户列出所有订单以及时间差(以分钟为单位):      - “收到”到“键入”为[TurnTime1]      - “键入”到“已打印”为[TurnTime2]      - “打印”到“已交付”为[TurnTime3]      - “收到”至“已交付”为[TurnTime4] 我还需要返回CustomerName,OrderTypeName,LoanNumber,TurnTime1,TurnTime2,TurnTime3和TurnTime4。我相信我很接近,但是,我尝试了两种不同的方式,这两种方式都不正确,而且我被卡住了。第一个选项,仅包含4行,其值为" 0"每个TurnTime专栏。第二个选项包括超过600行。我相信这应该只返回11行数据,也许还有一些额外的行,数据不符合规定。以下是我到目前为止的情况:

选项1

SELECT DISTINCT tblCustomer.CustomerName, tblOrderType.OrderTypeName, tblOrder.LoanNumber,
(DATEPART(mi,(tblOrderActivity.ActivityDate - tblOrderActivity.ActivityDate))) AS [TurnTime1],
(DATEPART(mi,(tblOrderActivity.ActivityDate - tblOrderActivity.ActivityDate))) AS [TurnTime2],
(DATEPART(mi,(tblOrderActivity.ActivityDate - tblOrderActivity.ActivityDate))) AS [TurnTime3],
(DATEPART(mi,(tblOrderActivity.ActivityDate - tblOrderActivity.ActivityDate))) AS [TurnTime4]
FROM tblOrder
INNER JOIN tblOrderActivity
ON tblOrder.OrderID = tblOrderActivity.OrderID
INNER JOIN tblActivity
ON tblOrderActivity.ActivityID = tblActivity.ActivityID
INNER JOIN tblOrderType
ON tblOrderType.OrderTypeID = tblOrder.OrderTypeID
INNER JOIN tblCustomer
ON tblCustomer.CustomerID = tblOrder.CustomerID
WHERE EXISTS (SELECT * FROM tblActivity WHERE ActivityName IS NOT NULL)
GROUP BY tblCustomer.CustomerName, tblOrderType.OrderTypeName, tblorder.LoanNumber, tblOrderActivity.ActivityDate;

选项2

SELECT DISTINCT tblCustomer.CustomerName, tblOrderType.OrderTypeName, tblOrder.LoanNumber,
(DATEPART(mi,(TT2.ActivityDate - TT1.ActivityDate))) AS [TurnTime1],
(DATEPART(mi,(TT3.ActivityDate - TT2.ActivityDate))) AS [TurnTime2],
(DATEPART(mi,(TT4.ActivityDate - TT3.ActivityDate))) AS [TurnTime3],
(DATEPART(mi,(TT4.ActivityDate - TT1.ActivityDate))) AS [TurnTime4]
FROM tblOrder
INNER JOIN tblOrderActivity AS TT1
ON tblOrder.OrderID = TT1.OrderID
INNER JOIN tblOrderActivity AS TT2
ON tblOrder.OrderID = TT2.OrderID
INNER JOIN tblOrderActivity AS TT3
ON tblOrder.OrderID = TT3.OrderID
INNER JOIN tblOrderActivity AS TT4
ON tblOrder.OrderID = TT4.OrderID
INNER JOIN tblActivity AS TA1
ON TT1.ActivityID = TA1.ActivityID
INNER JOIN tblActivity AS TA2
ON TT2.ActivityID = TA2.ActivityID
INNER JOIN tblActivity AS TA3
ON TT3.ActivityID = TA3.ActivityID
INNER JOIN tblActivity AS TA4
ON TT4.ActivityID = TA4.ActivityID
INNER JOIN tblOrderType
ON tblOrderType.OrderTypeID = tblOrder.OrderTypeID
INNER JOIN tblCustomer
ON tblCustomer.CustomerID = tblOrder.CustomerID
WHERE EXISTS (SELECT * FROM tblActivity WHERE ActivityName IS NOT NULL)
GROUP BY tblCustomer.CustomerName, tblOrderType.OrderTypeName, tblorder.LoanNumber, TT1.ActivityDate,
TT2.ActivityDate, TT3.ActivityDate, TT4.ActivityDate;

3 个答案:

答案 0 :(得分:1)

这个怎么样: SQL Fiddle

MS SQL Server 2008架构设置

create table tblCustomer
(
    CustomerID int,
    CustomerName varchar(max)
)
INSERT INTO tblCustomer
VALUES
(  1, 'ABC Bank'),
(  2, 'Chase Bank')

create table tblOrderType
(
    OrderTypeID int,
    OrderTypeName varchar(max)
)

INSERT INTO tblOrderType
VALUES
(  1, 'Assignment'),
(  2, 'LienRelease')


create table tblActivity
(
    ActivityID int,
    ActivityName varchar(max)
)

INSERT INTO tblActivity
VALUES
(  1, 'Received'),
(  2, 'Keyed'),
(  3, 'Printed'),
(  4, 'Delivered To Customer')

CREATE TABLE tblOrder
(
    OrderID int,
    CustomerID int,
    OrderTypeID int,
    LoanNumber int
)

INSERT INTO tblOrder
VALUES
(  1, 1, 1, 45584565),
(  2, 1, 1, 45566856),
(  3, 1, 1, 45565584),
(  4, 1, 1, 45588545)

CREATE TABLE tblOrderActivity
(
    OrderID int,
    ActivityID int,
    ActivityDate DateTime
)

INSERT INTO tblOrderActivity
VALUES
(1, 1, '2007-04-16 8:34:00 AM'),
(1, 2, '2007-04-16 9:22:00 AM'),  
(1, 3, '2007-04-16 9:51:00 AM'), 
(1, 4, '2007-04-16 4:14:00 PM'),  
(2, 1, '2007-04-16 8:34:00 AM'),
(2, 3, '2014-12-16 10:33:09 AM'),
(3, 1, '2007-04-16 8:34:00 AM'),
(3, 2, '2007-04-16 9:22:00 AM'),
(3, 3, '2007-04-16 9:51:00 AM'),
(3, 4, '2007-04-16 4:14:00 PM'),
(4, 1, '2007-04-16 8:34:00 AM'),
(4, 2, '2007-04-16 9:22:00 AM'),
(4, 3, '2007-04-16 9:51:00 AM') 

查询1

SELECT C.CustomerName,O.OrderId, OT.OrderTypeName, O.LoanNumber,
(DATEDIFF(mi, Received.ActivityDate, Keyed.ActivityDate)) AS [TurnTime1],
(DATEDIFF(mi, Keyed.ActivityDate, Printed.ActivityDate)) AS [TurnTime2],
(DATEDIFF(mi, Printed.ActivityDate, Delivered.ActivityDate)) AS [TurnTime3],
(DATEDIFF(mi, Received.ActivityDate, Delivered.ActivityDate)) AS [TurnTime4]
FROM tblCustomer C
INNER JOIN tblOrder O
    ON O.CustomerId = C.CustomerId
INNER JOIN tblOrderType OT
    ON OT.OrderTypeID = O.OrderTypeID
INNER JOIN tblOrderActivity Received
    ON Received.OrderID = O.OrderID AND Received.ActivityId = 1
LEFT JOIN tblOrderActivity Keyed
    ON Keyed.OrderID = O.OrderID AND Keyed.ActivityId = 2
LEFT JOIN tblOrderActivity Printed
    ON Printed.OrderID = O.OrderID AND Printed.ActivityId = 3
LEFT JOIN tblOrderActivity Delivered
    ON Delivered.OrderID = O.OrderID AND Delivered.ActivityId = 4

<强> Results

| CUSTOMERNAME | ORDERID | ORDERTYPENAME | LOANNUMBER | TURNTIME1 | TURNTIME2 | TURNTIME3 | TURNTIME4 |
|--------------|---------|---------------|------------|-----------|-----------|-----------|-----------|
|     ABC Bank |       1 |    Assignment |   45584565 |        48 |        29 |       383 |       460 |
|     ABC Bank |       2 |    Assignment |   45566856 |    (null) |    (null) |    (null) |    (null) |
|     ABC Bank |       3 |    Assignment |   45565584 |        48 |        29 |       383 |       460 |
|     ABC Bank |       4 |    Assignment |   45588545 |        48 |        29 |    (null) |    (null) |

如果您需要删除包含NULL的行,只需将LEFT JOIN更改为INNER JOIN

答案 1 :(得分:0)

<强> SQL Fiddle Demo

您可以使用case based aggregation减法来获得客户每个订单的活动之间的时间差异。

select C.CustomerNAme, OT.OrderTypeName, O.LoanNumber, 
      max ( case when OA.ActivityID =2 then datediff(minute,0,OA.ActivityDate) end)  - 
      max ( case When OA.ActivityID =1 then datediff(minute,0,OA.ActivityDate) end) as TurnTime1,
      max ( case when OA.ActivityID =3 then datediff(minute,0,OA.ActivityDate) end)  - 
      max ( case When OA.ActivityID =2 then datediff(minute,0,OA.ActivityDate) end) as TurnTime2,
      max ( case when OA.ActivityID =4 then datediff(minute,0,OA.ActivityDate) end)  - 
      max ( case When OA.ActivityID =3 then datediff(minute,0,OA.ActivityDate) end) as TurnTime3,
      max ( case when OA.ActivityID =4 then datediff(minute,0,OA.ActivityDate) end)  - 
      max ( case When OA.ActivityID =1 then datediff(minute,0,OA.ActivityDate) end) as TurnTime4


FROM tblCustomer C
JOIN tblOrder O
on C.CustomerID = O.CustomerID
JOIN tblOrderActivity OA
on OA.OrderID = O.OrderID
JOIN tblOrderType OT
on OT.OrderTypeID = O.OrderTypeID
GROUP BY C.CustomerName, OT.OrderTypeName, O.LoanNumber

答案 2 :(得分:0)

这应该只是根据表活动为您想要的每个组创建连接表的简单问题。请注意,我假设活动只能执行一次。

Select tblCustomer.CustomerName, 
       tblOrderType.OrderTypeName, 
       tblOrder.LoanNumber,
       DATEDiff(mi,tblOrderReceived.ActivityDate, tblOrderKeyed.ActivityDate) AS [TurnTime1],
       DATEDiff(mi,tblOrderKeyed.ActivityDate, tblOrderPrinted.ActivityDate) AS [TurnTime2],
       DATEDiff(mi,tblOrderPrinted.ActivityDate, tblOrderDelivered.ActivityDate) AS [TurnTime3],
       DATEDiff(mi,tblOrderReceived.ActivityDate, tblOrderDelivered.ActivityDate) AS [TurnTime4]
From tblOrder
    INNER JOIN tblOrderType
        ON tblOrderType.OrderTypeID = tblOrder.OrderTypeID
    INNER JOIN tblCustomer
        ON tblCustomer.CustomerID = tblOrder.CustomerID
    Left Outer Join tblOrderActivity tblOrderReceived
        ON tblOrder.OrderID = tblOrderActivity.OrderID
    Left Outer Join tblOrderActivity tblOrderKeyed
        ON tblOrder.OrderID = tblOrderActivity.OrderID
    Left Outer Join tblOrderActivity tblOrderPrinted
        ON tblOrder.OrderID = tblOrderActivity.OrderID
    Left Outer Join tblOrderActivity tblOrderDelivered
        ON tblOrder.OrderID = tblOrderActivity.OrderID
    Left Outer Join tblActivity
        ON tblOrderReceived.ActivityID = tblActivity.ActivityID
            OR tblOrderKeyed.ActivityID = tblActivity.ActivityID
            OR tblOrderPrinted.ActivityID = tblActivity.ActivityID
            OR tblOrderDelivered.ActivityID = tblActivity.ActivityID
Where tblOrderReceived.ActivityID = 1
    And tblOrderKeyed.ActivityID = 2
    And tblOrderPrinted.ActivityID = 3
    And tblOrderDelivered.ActivityID = 4
    And tblOrder.OrderID In (Select ActivityMask.OrderID from tblOrderActivity ActivityMask)