tags:

views:

30

answers:

2

I've got a query I wrote using a JOIN to display a summary using the part's Serial_Number.

Obviously, it does not work!

Using the direct search here:

select Serial_Number, Op_ID, Date_Time as 'DecayDate', 
    DECAY.System_ID AS 'DecayID', Test_Result as 'DecayResult' 
from Test_Results
where serial_number='CP21295 1006 09' and system_id like '%decay%'

I get this sample output:

Serial_Number     Op_ID   DecayDate               DecayID      DecayResult
CP21295 1006 09   003468  2009-10-15 06:36:13.643 AA_DECAY_6   FAILED
CP21295 1006 09   003468  2009-10-05 08:08:38.503 AA_DECAY_6   PASSED

Notice there were two (2) tests for this one part number that I need the result of.

Now to the query I created that does not work:


This first version will return ONE record:

SELECT LABEL.Serial_Number, 
  DECAY.Op_ID,
  DECAY.Date_Time AS 'DecayDate',
  DECAY.System_ID AS 'DecayID',
  CASE
    WHEN DECAY.Test_Result LIKE '%fail%' THEN 'FAIL'
    WHEN DECAY.Test_Result LIKE '%pass%' THEN 'PASS'
    ELSE NULL
  END AS 'DecayResult'
  FROM 
  ACP_Parts AS LABEL
  LEFT OUTER JOIN (
    SELECT I.Serial_Number, I.Op_ID, I.Date_Time, I.System_ID, I.Test_Result
        FROM Test_Results I
    LEFT OUTER JOIN Test_Results O ON (
        I.Serial_Number=O.Serial_Number) AND 
        (O.Date_Time<I.Date_Time) -- AND (O.Serial_Number IS NULL) // didn't work
    WHERE
        (I.Test_Result LIKE '%pass%' OR I.Test_Result LIKE '%fail%') AND 
        (I.System_ID like '%decay%') AND
        (O.Test_Result LIKE '%pass%' OR O.Test_Result LIKE '%fail%') AND
        (O.System_ID like '%decay%')
    ) AS DECAY ON 
        (LABEL.Serial_Number=DECAY.Serial_Number) AND 
        (LABEL.Date_Time<DECAY.Date_Time)
  WHERE 
    (LABEL.Serial_Number IN (
        SELECT DISTINCT Serial_Number 
        FROM ACP_Parts 
        WHERE (Serial_Number IS NOT NULL) AND 
         (DATEADD(yy, - 1, GETDATE()) < Date_Time)))

Output

Serial_Number     DecayOp DecayDate               DecayID              DecayResult
CP21295 1006 09   003468  2009-10-15 06:36:13.643 AA_DECAY_6           PASS 

I am guessing the above query produces a result because there are two or more records for it to compare. Right?


I modified the query above, hoping to return the newest record, but this version does not return anything:

SELECT LABEL.Serial_Number, 
  DECAY.Op_ID,
  DECAY.Date_Time AS 'DecayDate',
  DECAY.System_ID 'DecayID',
  CASE
    WHEN DECAY.Test_Result LIKE '%fail%' THEN 'FAIL'
    WHEN DECAY.Test_Result LIKE '%pass%' THEN 'PASS'
    ELSE NULL
  END AS 'DecayResult'
  FROM 
  ACP_Parts AS LABEL
  LEFT OUTER JOIN (
    SELECT TOP 1 Serial_Number, Op_ID, Date_Time, System_ID, Test_Result
    FROM Test_Results
    WHERE
      (System_ID like '%decay%') AND
      (Test_Result LIKE '%pass%' OR Test_Result LIKE '%fail%')
    ORDER BY Date_Time DESC
    ) AS DECAY ON 
        (LABEL.Serial_Number=DECAY.Serial_Number) AND 
        (LABEL.Date_Time<DECAY.Date_Time)
  WHERE 
    (LABEL.Serial_Number IN (
        SELECT DISTINCT Serial_Number 
        FROM ACP_Parts 
        WHERE (Serial_Number IS NOT NULL) AND 
         (DATEADD(yy, - 1, GETDATE()) < Date_Time)))

Output

Serial_Number     DecayOp DecayDate               DecayID              DecayResult
CP21295 1006 09   NULL    NULL                    NULL                 NULL

Could someone point out how I could get this query to return the single result that I'm after?

A: 

Am I right in thinking that you want the latest test_result record for each part?

Check out ROW_NUMBER() OVER (PARTITION BY... ORDER BY ...) in the MSDN docs - that'll make it blindingly simple - assuming you're using MSSQL 2005 or above.

Will A
Can't see it. Work uses a Microsoft ISA Proxy Server, and our Network Admin can't figure out how to get it to pass MSDN pages. They always time out.
jp2code
Rats. We are also stuck with SQL Server 2000 Enterprise.
jp2code
@jp2code - your work blocks msdn? How awful of a job could that really be. "Sure boss I can make it work if I could use the msdn documentation it would of been done last week. Now I have to go home and look at msdn to get the job done!"
JonH
@JonH - work does not actively block MSDN, but our Network Administrator can not see a way to get our Microsoft ISA Proxy Server to pass the site - especially if I am logged in using my MSDN account.
jp2code
@Will A: `Msg 195, Level 15, State 10: 'row_number' is not a recognized function name.` For one, I'm stuck with SQL Server 2000 Enterprise. Second, your hint still does not tell me how to solve my problem. My logic appears to be there. I do not, however, see how using your `row_number` would help - even if I **could** use it.
jp2code
A: 

OK, I've found ways to tweak the code to produce my desired results.

First, here is the data I used:

CREATE TABLE JP1 (Serial_Number VarChar(20), Date_Time DateTime, Test_Result VarChar(255))
INSERT JP1 VALUES ('T900 09', '2009-10-10 01:15:00.000', 'NO TEST, Failed to Dump')
INSERT JP1 VALUES ('T901 09', '2009-10-10 01:20:00.000', '(BLUE) PASS (WHITE) FAIL')

CREATE TABLE JP2 (Serial_Number VarChar(20), Date_Time DateTime, Test_Result VarChar(255))
INSERT JP2 VALUES ('T900 09', '2009-10-15 01:15:00.000', 'NO TEST, Failed to Dump')
INSERT JP2 VALUES ('T900 09', '2009-10-15 02:15:00.000', '(BLUE) PASS (WHITE) FAIL')
INSERT JP2 VALUES ('T900 09', '2009-10-15 04:25:00.000', 'TEST ABORTED')
INSERT JP2 VALUES ('T900 09', '2009-10-15 04:59:00.000', '(BLUE) FAIL (WHITE) FAIL')
INSERT JP2 VALUES ('T900 09', '2009-10-15 05:09:00.000', '(WHITE) NO TEST')
INSERT JP2 VALUES ('T900 09', '2009-10-15 05:34:00.000', 'B=Pass.,W=FAIL, Final Fill')
INSERT JP2 VALUES ('T900 09', '2009-10-15 06:06:00.000', 'PASSED PD')
INSERT JP2 VALUES ('T900 09', '2009-10-15 06:30:00.000', 'TEST ABORTED')
INSERT JP2 VALUES ('T900 09', '2009-10-15 06:36:00.000', 'PASS')
INSERT JP2 VALUES ('T900 09', '2009-10-15 06:50:00.000', 'FAIL')
INSERT JP2 VALUES ('T900 09', '2009-10-05 08:08:00.000', 'NO TEST, Operator cancel')

Next, I created two (2) very similar queries. It turns out, the requirements I set forth in the LEFT OUTER JOIN clause needs to be mimicked in the WHERE clause.

Here is how I extract the FIRST PASS result and date:

SELECT LABEL.Serial_Number, 
    DECAY.Date_Time AS 'DecayDate',
    CASE
    WHEN DECAY.Test_Result LIKE '%fail%' THEN 'FAIL'
    WHEN DECAY.Test_Result LIKE '%pass%' THEN 'PASS'
    ELSE NULL
    END AS 'DecayResult'
FROM JP1 AS LABEL
LEFT OUTER JOIN (
    SELECT I.Serial_Number, I.Date_Time, I.Test_Result
    FROM
        JP2 AS I
        LEFT OUTER JOIN JP2 AS O
        ON
        (I.Serial_Number=O.Serial_Number) AND
        ((O.Test_Result LIKE '%pass%') OR (O.Test_Result LIKE '%fail%')) AND -- //Gets First Test!
        (O.Test_Result NOT LIKE '%NO TEST%') AND
        (O.Date_Time<I.Date_Time) -- //(selects FIRST pass or fail)
        -- (I.Date_Time<O.Date_Time) -- //(selects LAST pass or fail)
    WHERE
        (I.Test_Result LIKE '%pass%' OR I.Test_Result LIKE '%fail%') AND -- //Gets First Test!
        (I.Test_Result NOT LIKE '%NO TEST%') AND
        (O.Serial_Number IS NULL)
) AS DECAY ON 
(LABEL.Serial_Number=DECAY.Serial_Number) AND 
(LABEL.Date_Time<DECAY.Date_Time)
WHERE 
(LABEL.Serial_Number IN (
    SELECT DISTINCT Serial_Number 
    FROM JP1
    WHERE (Serial_Number IS NOT NULL) AND 
    (DATEADD(yy, - 1, GETDATE()) < Date_Time))
)

Here is how I extract the FIRST Test result and date:

SELECT LABEL.Serial_Number, 
    DECAY.Date_Time AS 'DecayDate',
    CASE
    WHEN DECAY.Test_Result LIKE '%fail%' THEN 'FAIL'
    WHEN DECAY.Test_Result LIKE '%pass%' THEN 'PASS'
    ELSE NULL
    END AS 'DecayResult'
FROM JP1 AS LABEL
LEFT OUTER JOIN (
    SELECT I.Serial_Number, I.Date_Time, I.Test_Result
    FROM
        JP2 AS I
        LEFT OUTER JOIN JP2 AS O
        ON
        (I.Serial_Number=O.Serial_Number) AND
        ((O.Test_Result LIKE '%pass%') AND (O.Test_Result NOT LIKE '%fail%')) AND -- //Gets First Pass!
        (O.Test_Result NOT LIKE '%NO TEST%') AND
        (O.Date_Time<I.Date_Time) -- //(selects FIRST pass or fail)
        -- (I.Date_Time<O.Date_Time) -- //(selects LAST pass or fail)
    WHERE
        (I.Test_Result LIKE '%pass%' AND I.Test_Result NOT LIKE '%fail%') AND -- //Gets First Pass!
        (I.Test_Result NOT LIKE '%NO TEST%') AND
        (O.Serial_Number IS NULL)
) AS DECAY ON 
(LABEL.Serial_Number=DECAY.Serial_Number) AND 
(LABEL.Date_Time<DECAY.Date_Time)
WHERE 
(LABEL.Serial_Number IN (
    SELECT DISTINCT Serial_Number 
    FROM JP1
    WHERE (Serial_Number IS NOT NULL) AND 
    (DATEADD(yy, - 1, GETDATE()) < Date_Time))
)

I hope others find this useful!

~Joe

jp2code