T-SQL Optimization – Create a Pivot or Alter This Query?

optimizationpivott-sql

The following Query that I wrote is working to a point. The problem that I found is that in each pump, cable, etc can be listed in each of the part columns. Example:

enter image description here

What I would like to get is the well listed with each of the pumps, cables, etc that are there instead of what I am currently getting which is just the first pump, cable, etc.

Here is the query I am running:

        With CTE AS(
SELECT Pull_Date, Well_Name, Part1 Part, Part1_PN PartPN, Part1_SN PartSN FROM testtest
UNION ALL
    SELECT Pull_Date, Well_Name, Part2, Part2_PN, Part2_SN from testtest
UNION ALL
    SELECT Pull_Date, Well_Name, Part3, Part3_PN, Part3_SN from testtest
)

Select Pull_Date, Well_Name,
    MIN(CASE WHEN Part='BODH' THEN 'BODH' ELSE NULL END) [BODH],
    MIN(CASE WHEN Part='BODH' THEN PartPN Else NULL END) BODH_PN,
    MIN(CASE WHEN Part='BODH' THEN PartSN ELSE NULL END) BODH_SN,
    MIN(CASE WHEN Part='Cable' THEN 'Cable' ELSE NULL END) [Cable],
    MIN(CASE WHEN Part= 'Cable' THEN PartPN Else NULL END) Cable_PN,
    MIN(CASE WHEN Part= 'Cable' THEN PartSN ELSE NULL END) Cable_SN,
    MIN(CASE WHEN Part= 'Pump' THEN 'Pump' ELSE Null END) [Pump],
    MIN(CASE WHEN Part= 'Pump' THEN PartPN ELSE NULL END) Pump_PN,
    MIN(CASE WHEN Part= 'Pump' THEN PartSN ELSE NULL END) Pump_SN,
    MIN(CASE WHEN Part= 'MLE' THEN 'MLE' ELSE NULL END) [MLE],
    MIN(CASE WHEN Part= 'MLE' THEN PartPN ELSE NULL END) MLE_PN,
    MIN(CASE WHEN Part= 'MLE' THEN PartSN ELSE NULL END) MLE_SN,
    MIN(CASE WHEN Part= 'AGH' THEN 'AGH' ELSE NULL END) [AGH],
    MIN(CASE WHEN Part= 'AGH' THEN PartPN ELSE NULL END) AGH_PN,
    MIN(CASE WHEN Part= 'AGH' THEN PartSN ELSE NULL END) AGH_SN
FROM CTE
GROUP BY Pull_Date, Well_Name

And here is an example of what I am currently receiving:

enter image description here

I am not very familiar with SQL Server PIVOT or if this is even needed in this case.

I appreciate any assistance on this and thank you in advance.

EDIT:

Unfortunately I cannot add a picture of what I would like so I will try to explain it.

I would like to have it all in one row so it would look somewhat like this:

Pull Date| Well_Name | BODH1 | BODH1_PN | BODH1_SN | BODH2 | BODH2_PN | BODH2_SN

Pump, Cable, MLE, etc would also repeat. I have 20 part columns and would like to pull them so I could easily sort the pump1 through possibly pump5 (some wells have 5 some less). Eventually this data will be inserted into another table to update it.

EDIT 2:

Link to test data I created: SQLFiddle

Best Answer

This should work. I took the original CTE, partitioned by part and date and numbered those. This gave every part on each date it's own number starting with 1.

Then in the case statement, adding WHERE Number = N allows it so that each part is unique.

Finally, the column names were modified to have their respective numbers.

Since this is unwieldy, dynamic sql could be used to generate the repetitive code.

    With CTE AS (SELECT * FROM 
(SELECT ROW_NUMBER() OVER(PARTITION BY Part + Pull_Date ORDER BY PartSN) AS [Number], 
  Pull_Date, 
  Well_Name, 
  Part, 
  PartSN, 
  PartPN 
FROM (
SELECT Pull_Date, Well_Name, Part1 Part, Part1_PN PartPN, Part1_SN PartSN 
  FROM test
UNION ALL
    SELECT Pull_Date, Well_Name, Part2, Part2_PN, Part2_SN from test
UNION ALL
    SELECT Pull_Date, Well_Name, Part3, Part3_PN, Part3_SN from test
UNION ALL
    SELECT Pull_Date, Well_Name, Part4, Part4_PN, Part4_SN from test
UNION ALL
    SELECT Pull_Date, Well_Name, Part5, Part5_PN, Part5_SN from test
UNION ALL
    SELECT Pull_Date, Well_Name, Part6, Part6_PN, Part6_SN from test
) subquery) new
  )

 Select Pull_Date, Well_Name,
    MIN(CASE WHEN Part='BODH' AND Number=1 THEN 'BODH' ELSE NULL END) [BODH1],
    MIN(CASE WHEN Part='BODH' AND Number=1 THEN PartPN Else NULL END) BODH_PN1,
    MIN(CASE WHEN Part='BODH' AND Number=1 THEN PartSN ELSE NULL END) BODH_SN1,
    MIN(CASE WHEN Part='BODH' AND Number=2 THEN 'BODH' ELSE NULL END) [BODH2],
    MIN(CASE WHEN Part='BODH' AND Number=2 THEN PartPN Else NULL END) BODH_PN2,
    MIN(CASE WHEN Part='BODH' AND Number=2 THEN PartSN ELSE NULL END) BODH_SN2,

    MIN(CASE WHEN Part='Cable' AND Number=1 THEN 'Cable' ELSE NULL END) [Cable1],
    MIN(CASE WHEN Part= 'Cable' AND Number=1 THEN PartPN Else NULL END) Cable_PN1,
    MIN(CASE WHEN Part= 'Cable' AND Number=1 THEN PartSN ELSE NULL END) Cable_SN1,
    MIN(CASE WHEN Part='Cable' AND Number=2 THEN 'Cable' ELSE NULL END) [Cable2],
    MIN(CASE WHEN Part= 'Cable' AND Number=2 THEN PartPN Else NULL END) Cable_PN2,
    MIN(CASE WHEN Part= 'Cable' AND Number=2 THEN PartSN ELSE NULL END) Cable_SN2,

    MIN(CASE WHEN Part= 'Pump' AND Number=1 THEN 'Pump' ELSE Null END) [Pump1],
    MIN(CASE WHEN Part= 'Pump' AND Number=1 THEN PartPN ELSE NULL END) Pump_PN1,
    MIN(CASE WHEN Part= 'Pump' AND Number=1 THEN PartSN ELSE NULL END) Pump_SN1,
    MIN(CASE WHEN Part= 'Pump' AND Number=2 THEN 'Pump' ELSE Null END) [Pump2],
    MIN(CASE WHEN Part= 'Pump' AND Number=2 THEN PartPN ELSE NULL END) Pump_PN2,
    MIN(CASE WHEN Part= 'Pump' AND Number=2 THEN PartSN ELSE NULL END) Pump_SN2,

    MIN(CASE WHEN Part= 'MLE' AND Number=1 THEN 'MLE' ELSE NULL END) [MLE1],
    MIN(CASE WHEN Part= 'MLE' AND Number=1 THEN PartPN ELSE NULL END) MLE_PN1,
    MIN(CASE WHEN Part= 'MLE' AND Number=1 THEN PartSN ELSE NULL END) MLE_SN1,
    MIN(CASE WHEN Part= 'MLE' AND Number=2 THEN 'MLE' ELSE NULL END) [MLE2],
    MIN(CASE WHEN Part= 'MLE' AND Number=2 THEN PartPN ELSE NULL END) MLE_PN2,
    MIN(CASE WHEN Part= 'MLE' AND Number=2 THEN PartSN ELSE NULL END) MLE_SN2,

    MIN(CASE WHEN Part= 'AGH' AND Number=1 THEN 'AGH' ELSE NULL END) [AGH1],
    MIN(CASE WHEN Part= 'AGH' AND Number=1 THEN PartPN ELSE NULL END) AGH_PN1,
    MIN(CASE WHEN Part= 'AGH' AND Number=1 THEN PartSN ELSE NULL END) AGH_SN1,
    MIN(CASE WHEN Part= 'AGH' AND Number=2 THEN 'AGH' ELSE NULL END) [AGH2],
    MIN(CASE WHEN Part= 'AGH' AND Number=2 THEN PartPN ELSE NULL END) AGH_PN2,
    MIN(CASE WHEN Part= 'AGH' AND Number=2 THEN PartSN ELSE NULL END) AGH_SN2

FROM CTE
GROUP BY Pull_Date, Well_Name