views:

71

answers:

2

Am interested to know how correct is my query the question is posted here., I doubt If I have written a perfect one, and I wish to ask you all where can I improve my code.

Note: I did not want to fill this place up with lot of code, was very brief. Thank you.

SELECT a.BookingId                         AS BookingId,
       CAST(b.TransactionDateTime AS DATE) AS TransactionDate
FROM   TC33_AuditTrial A
       JOIN TC33_AuditTrial b
       ON     a.AuditId                    = b.AuditId
WHERE  a.TransactionType                   = 'S'
AND    CAST(a.TransactionDateTime AS DATE) =
       (SELECT CAST(b.TransactionDateTime AS DATE)
       FROM    TC33_AuditTrial b
       WHERE   b.BookingId = a.BookingId
       AND     b.AuditId   =
               (SELECT MAX(b.AuditId)
               FROM    TC33_AuditTrial b
               WHERE   a.BookingId       = b.BookingId
               AND     b.TransactionType = 'R'
               )
       )
AND    a.TransactionValue =
       (SELECT SUM(b.TransactionValue)
       FROM    TC33_AuditTrial b
       WHERE   a.BookingId       = b.BookingId
       AND     b.TransactionType = 'R'
       )
+3  A: 

Undeleted

My original answer was

SELECT BookingId, CONVERT(VARCHAR(8), TransactionDateTime, 112) AS TransactionDate
FROM TC33_AuditTrial
GROUP BY BookingId, CONVERT(VARCHAR(8), TransactionDateTime, 112)
HAVING 
SUM(CASE TransactionType WHEN 'S' THEN TransactionValue END) <= 
SUM(CASE TransactionType WHEN 'R' THEN TransactionValue END)
ORDER BY BookingID

Which I was quite pleased with as it just took one pass through the data.

Then I noticed the updated bit of the spec that it has to be restricted to the first date that contains an entry for that booking. The only way I could think to do this was to add a sub query that increased the cost of the query quite dramatically.

The frustrating aspect though is that I want to restrict the results to the first day for each BookingId and I am already grouping by BookingId, Day

It feels like there might be some clever way of getting this restriction without the sub query but if so it has eluded me so far!

I just managed to get the 'OVER' working. I wouldn't have posted this answer until after the competition was closed except it has exactly the same query plan as the one posted by 8kb

WITH X AS
(
SELECT   BookingId,
         RANK() OVER(PARTITION BY BookingId ORDER BY CONVERT(VARCHAR(8), TransactionDateTime, 112)) AS Rnk,
         CONVERT(VARCHAR(8), TransactionDateTime, 112) AS TransactionDate,
         SUM(CASE TransactionType WHEN 'S' THEN TransactionValue END) AS S,
         SUM(CASE TransactionType WHEN 'R' THEN TransactionValue END) AS R
FROM     TC33_AuditTrial t1
GROUP BY BookingId,
         CONVERT(VARCHAR(8), TransactionDateTime, 112)
)

SELECT BookingId, TransactionDate
FROM X
WHERE Rnk = 1 AND S<=R
ORDER BY BookingID
Martin Smith
+1: Wish I'd thought of it.
OMG Ponies
@OMG Shame there isn't any syntax like `AND PARTITION_NUMBER(CONVERT(VARCHAR(8), TransactionDateTime, 112)) = 1` though!
Martin Smith
Thank you, I never imagined the query could be written in simple lines.
Chaitanya
Also thanks for correcting me as the date has to be in "yyyymmdd format". I will try another time now. Thanks though for the learning i had :)
Chaitanya
@Martin: You can use OVER to get analytical functionality. Assuming SQL Server 2005+, for anyone else reading this.
OMG Ponies
@OMG - Yep I had a bash at that earlier and it seemed to make things worse. I must have been doing it wrong! Cheers.
Martin Smith
+1  A: 

Had to jump in too...

SELECT
  BookingID,
  CONVERT(VARCHAR(8), TransactionDateTime, 112) AS TransactionDate
FROM (
SELECT 
  BookingID,
  TransactionDateTime,
  COALESCE(pvt.S,0) AS Sale,
  COALESCE(pvt.R,0) AS Receipt,
  ROW_NUMBER() OVER (
    PARTITION BY BookingID ORDER BY (TransactionDateTime)) AS Rn
FROM (
  SELECT
    BookingID,
    DATEADD(DD, DATEDIFF(DD,0,TransactionDateTime), 0) AS TransactionDateTime,
    TransactionType,
    TransactionValue
  FROM TC33_AuditTrial
  ) t
PIVOT (
  SUM(TransactionValue)
  FOR TransactionType IN (S,R)
) AS pvt
) t2
WHERE Receipt >= Sale
AND Rn = 1
8kb
+1. Surprised how similar the execution plan for our 2 answers is.
Martin Smith
Is it terrible that I compared IO stats beforehand? Saw no difference. But didn't want to post if it got blown out of the water...
8kb
I think there basically is no difference. Only thing that is a bit strange is that even when I put them both in a stored procedure with the same length name for some reason I find yours consistently sends 13% more bytes back from the server according to the client stats in Management Studio.
Martin Smith