?
Solved

T-SQL Challenge

Posted on 2005-05-11
8
Medium Priority
?
1,211 Views
Last Modified: 2007-12-19
I have two tables, shipping(parent) and shippingStatus(Child). Sample Data:

shipping:
shipID, packageType, Date,

1, box, jun 5
2,  letter, jun 5

shippingStatus:
shipStatusID, shipID, shipStatus, GetDateTime()
1,1, scanned, jun5 12AM
2,1, in-route, jun5  1AM
3,1, in-route, jun5 1AM
4,1, delivered, jun5 7AM
5,2, scanned, jun5 12AM
6,2, in-route, jun5  1AM
7,2, in-route, jun5 1AM
8,2, in-route, jun5 7AM

How do i figure out the time between 2 statuses where the statuses are parameters.

For example I want the time difference when it was scanned to when it was first in-route for the box? example output:
PackageType, FirstOrdinal, SecondOrdinal, TimeDiff
Box, jun5 12AM, Jun5 1 AM, 1 hour diff
0
Comment
Question by:vinny45
  • 3
  • 2
  • 2
  • +1
8 Comments
 
LVL 28

Accepted Solution

by:
rafrancisco earned 2000 total points
ID: 13982258
Try this:

SELECT S.PackageType, A.GetDateTime AS FirstOrdinal, B.GetDateTime AS SecondOrdinal,
DATEDIFF(H, A.GetDateTime, B.GetDateTime) AS TimeDiff
FROM Shipping S INNER JOIN (
SELECT ShipID, MIN(GetDateTime) AS GetDateTime
FROM ShippingStatus
WHERE ShipStatus = 'scanned'
GROUP BY ShipID) A
ON S.ShipID = A.ShipID
INNER JOIN (
SELECT ShipID, MIN(GetDateTime) AS GetDateTime
FROM ShippingStatus
WHERE ShipStatus = 'in-route'
GROUP BY ShipID) B
ON A.[ShipID] = B.[ShipID]
0
 
LVL 34

Expert Comment

by:Brian Crowe
ID: 13982525
First I'm a little confused by the "GetDateTime()" as a field name so I'll just call it StatusDate

SELECT Shipping.PackageType,
     Scanned.StatusDate AS ScanDate,
     InRoute.StatusDate AS InRouteDate,
     Delivered.StatusDate AS DeliveredDate,
     DATEDIFF(hour, InRoute.StatusDate, Scanned.StatusDate) AS InRouteTime,
     DATEDIFF(hour, Delivered.StatusDate, InRoute.StatusDate) AS DeliveryTime,
FROM Shipping
INNER JOIN shippingstatus Scanned
     ON Shipping.shipID = Scanned.shipID
     AND Scanned.shipStatus = 'scanned'
LEFT OUTER JOIN shippingstatus InRoute
     ON Shipping.shipID = InRoute.shipID
     AND InRoute.shipStatus = 'in-route'
LEFT OUTER JOIN shippingstatus Delivered
     ON Shipping.shipID = Delivered.shipID
     AND Delivered.shipStatus = 'delivered'

There is probably some NULL checking that needs to be handled in the SELECT portion...
0
 
LVL 34

Expert Comment

by:Brian Crowe
ID: 13982551
correction...i forgot to take into account the multiple 'in-route' records

SELECT Shipping.PackageType,
     Scanned.StatusDate AS ScanDate,
     InRoute.StatusDate AS InRouteDate,
     Delivered.StatusDate AS DeliveredDate,
     DATEDIFF(hour, InRoute.StatusDate, Scanned.StatusDate) AS InRouteTime,
     DATEDIFF(hour, Delivered.StatusDate, InRoute.StatusDate) AS DeliveryTime,
FROM Shipping
INNER JOIN shippingstatus Scanned
     ON Shipping.shipID = Scanned.shipID
     AND Scanned.shipStatus = 'scanned'
LEFT OUTER JOIN (SELECT ShipID, Max(StatusDate) FROM shippingstatus WHERE ShipStatus = 'in-route' GROUP BY ShipID) AS InRoute
     ON Shipping.shipID = InRoute.shipID
LEFT OUTER JOIN shippingstatus Delivered
     ON Shipping.shipID = Delivered.shipID
     AND Delivered.shipStatus = 'delivered'
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 28

Expert Comment

by:rafrancisco
ID: 13982562
BriCrowe, you should be using the MIN(StatusDate) because they need the first in-route status.
0
 
LVL 70

Expert Comment

by:Scott Pletcher
ID: 13982589
DECLARE @status1 VARCHAR(30) --<<-- change as needed
DECLARE @status2 VARCHAR(30) --<<-- change as needed

SET @status1 = 'scanned' --<<-- change as needed or input param in sp
SET @status2 = 'in-route' --<<-- change as needed or input param in sp


SELECT s.packageType, ss.MinStatus1, ss.MinStatus2,
      CAST(DATEDIFF(MINUTE, ss.MinStatus1, ss.MinStatus2) / 60.0 AS DECIMAL(4,1)) AS [TimeDiff (Hours)]
FROM shipping s
INNER JOIN (
      SELECT shipID,
            MIN(CASE WHEN status = @status1 THEN GetDateTime ELSE '19000101' END) AS MinStatus1,
            MIN(CASE WHEN status = @status2 THEN GetDateTime ELSE '19000101' END) AS MinStatus2
      FROM shippingStatus
      GROUP BY shipID
      -- only select shipments that have rows in both statuses  --<<--chg if needed
      HAVING MIN(CASE WHEN status = @status1 THEN GetDateTime ELSE '19000101' END) > '19000101'
          AND MIN(CASE WHEN status = @status2 THEN GetDateTime ELSE '19000101' END) > '19000101'
) AS ss ON s.shipID = ss.shipID
0
 
LVL 70

Expert Comment

by:Scott Pletcher
ID: 13982604
That approach requires only one pass thru the shippingStatus table: multiple subqueries or joins will require multiple scans of the table.
0
 
LVL 70

Expert Comment

by:Scott Pletcher
ID: 13982620
To vinny45 (requestor):

Be careful when using DATEDIFF(HOUR, ...): DATEDIFF only checks boundaries, so, for example, the time difference between 12:59 PM and 2:00 PM will show as 2 hours (!).
0
 

Author Comment

by:vinny45
ID: 13988058
rafrancisco examplee worked, thanks all, maybe i couldn't understand the others. sorry for my shortcomings
0

Featured Post

Hire Technology Freelancers with Gigs

Work with freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely, and get projects done right.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

I have a large data set and a SSIS package. How can I load this file in multi threading?
One of the most important things in an application is the query performance. This article intends to give you good tips to improve the performance of your queries.
Via a live example, show how to extract information from SQL Server on Database, Connection and Server properties
Viewers will learn how to use the SELECT statement in SQL to return specific rows and columns, with various degrees of sorting and limits in place.
Suggested Courses

839 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question