2015-09-21 17 views
5

questa domanda è basata sul mio Previous Question. Ho bisogno di estendere la query in modo da poter incorporare altre due tabelle (in esecuzione su un'altra istanza del server).TSQL: estensione della query composta da cross apply e pivot

In questo Fiddle ho aggiunto queste due tabelle:

CREATE TABLE LookUp 
([docID] varchar(10), [docType] varchar(100), [PartNumber] varchar(100), [internalID] varchar(100)); 
INSERT INTO LookUp 
([docID],[docType],[PartNumber], [internalID]) 
VALUES 
    ('D0305415', 'docTypeSub', 'X0455', null), 
    ('D0157632', 'docTypeMain', null, 'XY05570-XY05571'), 
    ('D0181511', 'docTypeMain',null, 'XY05572-XY05573'), 
    ('D0157633', 'docTypeMain', null, 'XY06380-XY06381'), 
    ('D0156037', 'docTypeSub', 'X0326', null), 
    ('D0151874', 'docTypeMain', null, 'XY05345'); 

CREATE TABLE Links 
    ([docIDTop] varchar(10), [docIDBottom] varchar(10)); 
INSERT INTO Links 
    ([docIDTop],[docIDBottom]) 
VALUES 
    ('D0157632', 'D0305415'), 
    ('D0181511', 'D0305415'), 
    ('D0157633', 'D0305415'), 
    ('D0151874', 'D0156037'); 

quanto riguarda l'uscita devo visualizzare il nuovo InternalID colonna in una colonna separate da virgole basato sul colonna PartNumber.

Questa è la query che emette i dati corretti:

select c.docType AS c_docTypeSub, c.docID AS C_docID, c.PartNumber AS C_PartNumber , 
b.docIDTop AS B_docIdTop, b.docIDBottom AS B_docIdBottom, a.* 
FROM LookUp a, Links b, LookUp c 
WHERE a.docType = 'docTypeMain' 
and a.docID = b.docIDTop and b.docIDBottom = c.docID 
and c.docType = 'docTypeSub' 
; 

Il mio problema è quello di mettere i pezzi insieme in modo che posso ottenere il InternalID per mostrare nella mia vecchia domanda sotto:

---------------- 
-- OLD Query -- 
---------------- 
WITH CTE_no_nums 
AS 
(
SELECT docID, 
     CASE 
      WHEN PATINDEX('%[0-9]%',column1) > 0 
       THEN SUBSTRING(column1,0,PATINDEX('%[0-9]%',column1)) 
      ELSE column1 
     END AS cols, 
     COALESCE(column2,column3) AS vals 
FROM miscValues 
WHERE  column2 IS NOT NULL 
     OR column3 IS NOT NULL 
), 
CTE_Pivot 
    AS 
    (
    SELECT docID,partNumber,prio,[length],material 
    FROM CTE_no_nums 
    PIVOT 
    (
     MAX(vals) FOR cols IN (partNumber,prio,[length],material) 
    ) pvt 
) 

SELECT A.docId + ' # ' + B.vals AS [DocID # Plant], 
     A.docID, 
     A.partNumber, 
     A.prio, 
     B.vals AS Plant, 
     A.partNumber + '#' + A.material + '#' + A.[length] AS Identification, 
     A.[length], 
     SUBSTRING(CA.colors,0,LEN(CA.colors)) colors --substring removes last comma 
FROM CTE_Pivot A 
INNER JOIN CTE_no_nums B 
    ON  A.docID = B.docID 
     AND B.cols = 'Plant' 
CROSS APPLY ( SELECT vals + ',' 
       FROM CTE_no_nums C 
       WHERE cols = 'Color' 
        AND C.docID = A.docID 
       FOR XML PATH('') 
      ) CA(colors) 
      ; 

Spero che tu possa mostrarmi come questo può essere raggiunto. Se qualcosa non è chiaro, non esitate a chiedere. E no, non sono responsabile della struttura dati :-)

Grazie.

+0

tuo due set di dati di violino non sembrano condividere alcuna comunanza. Se, infatti, si sarebbe in grado di cercare da un Numero parte nella tabella MiscValues ​​a un Numero parte nella tabella LookUp, penso che il problema si risolva da solo. Rifai i dati e dovresti essere in grado di capirlo da lì. Allo stesso modo se i campi docID in LookUp o Links corrispondono a docID in Documento o MiscValues, il problema è risolto. Se questo non è il caso, non hai dati relazionali e questo non è possibile. –

+0

Ciao Tony, sarebbe bello se voti le risposte utili e accetti quello che ti ha aiutato a risolvere il tuo problema, grazie! – Shnugo

risposta

2

Juan Ruiz de Castilla ha esteso la mia risposta data e mi ha aperto gli occhi per i tuoi "link" -table.

Questo è il mio suggerimento finale, risolvendo il problema in un altro CTE:

CREATE TABLE MiscValues 
    ([docID] varchar(10) ,[rowNumber] int, [Column1] varchar(100), [Column2] varchar(100) 
    , [Column3] varchar(100)) 
; 
INSERT INTO MiscValues 
    ([docID],[rowNumber],[Column1], [Column2], [Column3]) 
VALUES 
    ('D0001',1, 'PartNumber', 'X0455', NULL), 
    ('D0001',2, 'Prio', '1', NULL), 
    ('D0001',3, 'Plant1', NULL, NULL), 
    ('D0001',4, 'Plant2', 'PlantB', NULL), 
    ('D0001',5, 'Plant3', 'PlantC', NULL), 
    ('D0001',6, 'Plant4', NULL, NULL), 
    ('D0001',7, 'Color1', 'white', NULL), 
    ('D0001',8, 'Color2', 'black', NULL), 
    ('D0001',9, 'Color3', 'blue', NULL), 
    ('D0001',10, 'Material', 'MA123', NULL), 
    ('D0001',11, 'Length', NULL, '10.87'), 

    ('D0002',1, 'PartNumber', 'X0326', NULL), 
    ('D0002',2, 'Prio', '2', NULL), 
    ('D0002',3, 'Plant1', 'PlantA', NULL), 
    ('D0002',4, 'Plant2', NULL, NULL), 
    ('D0002',5, 'Plant3', 'PlantC', NULL), 
    ('D0002',6, 'Plant4', 'PlantD', NULL), 
    ('D0002',7, 'Color1', NULL, NULL), 
    ('D0002',8, 'Color2', 'black', NULL), 
    ('D0002',9, 'Color3', NULL, NULL), 
    ('D0002',10, 'Color4', 'yellow', NULL), 
    ('D0002',11, 'Material', 'MA456', NULL), 
    ('D0002',12, 'Length', NULL, '16.43') 
; 

CREATE TABLE LookUp([docID] varchar(10), [docType] varchar(100), [PartNumber] varchar(100), [internalID] varchar(100)); 
INSERT INTO LookUp([docID],[docType],[PartNumber], [internalID]) 
VALUES 
    ('D0305415', 'docTypeSub', 'X0455', null), 
    ('D0157632', 'docTypeMain', null, 'XY05570-XY05571'), 
    ('D0181511', 'docTypeMain',null, 'XY05572-XY05573'), 
    ('D0157633', 'docTypeMain', null, 'XY06380-XY06381'), 
    ('D0156037', 'docTypeSub', 'X0326', null), 
    ('D0151874', 'docTypeMain', null, 'XY05345'); 

CREATE TABLE Links ([docIDTop] varchar(10), [docIDBottom] varchar(10)); 
INSERT INTO Links ([docIDTop],[docIDBottom]) 
VALUES 
    ('D0157632', 'D0305415'), 
    ('D0181511', 'D0305415'), 
    ('D0157633', 'D0305415'), 
    ('D0151874', 'D0156037'); 

WITH CTE_no_nums 
AS 
(
SELECT docID, 
     CASE 
      WHEN PATINDEX('%[0-9]%',column1) > 0 
       THEN SUBSTRING(column1,0,PATINDEX('%[0-9]%',column1)) 
      ELSE column1 
     END AS cols, 
     COALESCE(column2,column3) AS vals 
FROM miscValues 
WHERE  column2 IS NOT NULL 
     OR column3 IS NOT NULL 
), 
CTE_Pivot 
    AS 
    (
    SELECT docID,partNumber,prio,[length],material 
    FROM CTE_no_nums 
    PIVOT 
    (
     MAX(vals) FOR cols IN (partNumber,prio,[length],material) 
    ) pvt 
), 
CTE_InternalIDs AS 
(
     SELECT * 
     ,STUFF 
     ( 
     (SELECT ', ' + internalID 
     FROM LookUp AS L2 
     INNER JOIN Links L ON L2.docID=L.docIDTop 
     WHERE L2.internalID IS NOT NULL 
      AND L.docIDBottom=L1.docID 
     FOR XML PATH('') 
    ),1,2,'') AS ConcatenatedInternalIDs 
FROM LookUp AS L1 
WHERE L1.internalID IS NULL 
) 
SELECT A.docId + ' # ' + B.vals AS [DocID # Plant], 
     A.docID, 
     A.partNumber, 
     A.prio, 
     B.vals AS Plant, 
     A.partNumber + '#' + A.material + '#' + A.[length] AS Identification, 
     A.[length], 
     SUBSTRING(CA.colors,0,LEN(CA.colors)) colors, --substring removes last comma 
     IIDs.ConcatenatedInternalIDs 
FROM CTE_Pivot A 
INNER JOIN CTE_no_nums B 
    ON  A.docID = B.docID 
     AND B.cols = 'Plant' 
INNER JOIN CTE_InternalIDs AS IIDs ON A.partNumber = IIDs.PartNumber 
CROSS APPLY ( SELECT vals + ',' 
       FROM CTE_no_nums C 
       WHERE cols = 'Color' 
        AND C.docID = A.docID 
       FOR XML PATH('') 
      ) CA(colors) 
      ; 
--Clean up... 
/* 
DROP TABLE Links; 
DROP TABLE LookUp; 
DROP TABLE miscValues; 
*/ 

È possibile che torna con questo:

D0001 # PlantB D0001 X0455 1 PlantB X0455#MA123#10.87 10.87 white,black,blue XY05570-XY05571, XY05572-XY05573, XY06380-XY06381 
D0001 # PlantC D0001 X0455 1 PlantC X0455#MA123#10.87 10.87 white,black,blue XY05570-XY05571, XY05572-XY05573, XY06380-XY06381 
D0002 # PlantA D0002 X0326 2 PlantA X0326#MA456#16.43 16.43 black,yellow XY05345 
D0002 # PlantC D0002 X0326 2 PlantC X0326#MA456#16.43 16.43 black,yellow XY05345 
D0002 # PlantD D0002 X0326 2 PlantD X0326#MA456#16.43 16.43 black,yellow XY05345 

EDIT: Da qui in poi troverete il mio primo risposta (per comprendere la risposta di Juan Ruiz):

Non sono assolutamente sicuro, se ho capito bene ... Si desidera aggiungere un elenco concatenato alla query con tutte le voci internalID fi in base al numero parte di LookUp.

Il problema che avete: Non v'è alcun tipo di ordinamento implicito ...

Il tuo inserimento di

VALUES 
    ('D0305415', 'docTypeSub', 'X0455', null), 
    ('D0157632', 'docTypeMain', null, 'XY05570-XY05571'), 
    ('D0181511', 'docTypeMain',null, 'XY05572-XY05573'), 
    ('D0157633', 'docTypeMain', null, 'XY06380-XY06381'), 
    ('D0156037', 'docTypeSub', 'X0326', null), 
    ('D0151874', 'docTypeMain', null, 'XY05345'); 

sembra "legare" i valori "XY05570-XY05571", "XY05572-XY05573" e "XY06380-XY06381" al PartNumber "X0455" e il valore "XY05345" al PartNumber "X0326". Ma questo è sbagliato !!!

Si può fare in questo modo

VALUES 
    ('D0305415', 'docTypeSub', 'X0455', null), 
    ('D0157632', 'docTypeMain', 'X0455', 'XY05570-XY05571'), 
    ('D0181511', 'docTypeMain','X0455', 'XY05572-XY05573'), 
    ('D0157633', 'docTypeMain', 'X0455', 'XY06380-XY06381'), 
    ('D0156037', 'docTypeSub', 'X0326', null), 
    ('D0151874', 'docTypeMain', 'X0326', 'XY05345'); 

Oppure è possibile aggiungere una colonna IDENTITY e giocherellare con tutte le voci tra quelle che hanno InternalID IS NULL.

Con la prima (compilare la colonna PartNumber per ogni riga) è possibile ottenere la lista concatenata in questo modo:

select c.docType AS c_docTypeSub, c.docID AS C_docID, c.PartNumber AS C_PartNumber , 
b.docIDTop AS B_docIdTop, b.docIDBottom AS B_docIdBottom, a.*, 
STUFF((SELECT ', ' + x.internalID 
     FROM LookUp AS x 
     WHERE x.PartNumber=c.PartNumber 
     FOR XML PATH(''),TYPE).value('.','nvarchar(max)'),1,2,'') AS ConcatInternalID 
FROM LookUp a, Links b, LookUp c 
WHERE a.docType = 'docTypeMain' 
and a.docID = b.docIDTop and b.docIDBottom = c.docID 
and c.docType = 'docTypeSub' 
; 

Di couse è possibile aggiungere questo al vostro "vecchio query" così:

Basta aggiungere questo alla finale SELEZIONARE

[...CTEs before...] 
SELECT A.docId + ' # ' + B.vals AS [DocID # Plant], 
     A.docID, 
     A.partNumber, 
     A.prio, 
     B.vals AS Plant, 
     A.partNumber + '#' + A.material + '#' + A.[length] AS Identification, 
     A.[length], 
     SUBSTRING(CA.colors,0,LEN(CA.colors)) colors, --substring removes last comma 
     STUFF((SELECT ', ' + x.internalID 
     FROM LookUp AS x 
     WHERE x.PartNumber=A.PartNumber 
     FOR XML PATH(''),TYPE).value('.','nvarchar(max)'),1,2,'') AS ConcatInternalID 
[...FROM...] 

Speranza ho capito bene e questo può aiutare a ...

2

Sulla base @Shnugo risposta provare questo non non ottimizzata (ancora) risposta, penso che @Shnugo controllare Indifferente la tabella di collegamento, perché non c'è bisogno di modificare le informazioni di dati:

[...CTEs before...] 
    SELECT A.docId + ' # ' + B.vals AS [DocID # Plant], 
    A.docID, 
    A.partNumber, 
    A.prio, 
    B.vals AS Plant, 
    A.partNumber + '#' + A.material + '#' + A.[length] AS Identification, 
    A.[length], 
    SUBSTRING(CA.colors,0,LEN(CA.colors)) colors, --substring removes last comma 
    STUFF((SELECT ', ' + X.internalID 
    FROM LOOKUP X 
    INNER JOIN LINKS Z 
    ON X.DOCID = Z.DOCIDTOP 
    INNER JOIN LOOKUP X2 
    ON X2.DOCID = Z.DOCIDBOTTOM 
    WHERE X2.PartNumber=A.PartNumber 
    FOR XML PATH(''),TYPE).value('.','nvarchar(max)'),1,2,'') AS ConcatInternalID 
[...FROM...] 
+1

Grazie per avermi aperto gli occhi per la tabella Links ... Hai ragione, che le informazioni mancanti si trovano lì ... Ho cambiato la mia risposta. Un preventivo per te da parte mia – Shnugo