2009-12-16 16 views
7

Ho passato gli ultimi due giorni a lavorare su questo e sto girando in tondo.Sintassi SQL per ruotare tabelle multiple

La mia domanda è basato intorno la risposta che ho accettato in questo post: stackoverflow question

Ora ho i miei dati spostati da una singola tabella 400 colonna in una struttura di database molto più gestibile con molte grazie a Damir Sudarevic.

mio database si presenta così:

alt text

CREATE TABLE JobFiles (
    JobID UNIQUEIDENTIFIER PRIMARY KEY, 
    MachineID UNIQUEIDENTIFIER REFERENCES Machines(MachineID), 
    [Desc] NVARCHAR(MAX), 
    Name NVARCHAR(255), 
    JobOpen BIT, 
    [CreateDate] DATETIME NOT NULL DEFAULT GETDATE(), 
    [ModifyDate] DATETIME NOT NULL DEFAULT GETDATE(), 
    [CreatedByUser] NVARCHAR(64) DEFAULT '', 
    [ModifiedByUser] NVARCHAR(64) DEFAULT '') 
GO 

CREATE TABLE JobParamType (
    ParamTypeID UNIQUEIDENTIFIER PRIMARY KEY, 
    Name NVARCHAR(255), 
    [Desc] NVARCHAR(MAX), 
    IsTrait NVARCHAR) 

GO 
CREATE TABLE JobParamGroup (
    ParamGroupID UNIQUEIDENTIFIER PRIMARY KEY, 
    Name NVARCHAR(255), 
    [Desc] NVARCHAR(MAX)) 

GO 


CREATE TABLE JobParams (
    ParamID UNIQUEIDENTIFIER PRIMARY KEY, 
    ParamTypeID UNIQUEIDENTIFIER REFERENCES JobParamType(ParamTypeID), 
    ParamGroupID UNIQUEIDENTIFIER REFERENCES JobParamGroup(ParamGroupID), 
    JobFileID UNIQUEIDENTIFIER REFERENCES JobFiles(JobID), 
    IsEnabled BIT) 

GO 

-- Text based property 
CREATE TABLE JobTrait (
    ParamID UNIQUEIDENTIFIER PRIMARY KEY REFERENCES JobParams(ParamID), 
    Value NVARCHAR(MAX)) 
GO 

-- Numeric based property 
CREATE TABLE JobMeasurement (
    ParamID UNIQUEIDENTIFIER PRIMARY KEY REFERENCES JobParams(ParamID), 
    Value FLOAT, 
    Format NVARCHAR(20), 
    Unit NVARCHAR(MAX)) 
GO 

Tuttavia, per una particolare funzione della mia applicazione ho bisogno di elencare ogni riga JobParamType.Name come colonne che contengono una o JobMeasurement.Value JobTrait. Valore come dati per ogni JobFiles.Name.

JobParamType.IsTrait viene utilizzato per determinare se un valore è una misura o un tratto.

cioè

JobName | ParamName1  | ParamName2  | ParamName3  ... | ParamName400 
"MyJob"  MesurementValue TraitValue   MesurementValue ... TraitValue 
"TestJob" MesurementValue TraitValue   MesurementValue ... TraitValue 
"Job2"  MesurementValue TraitValue   MesurementValue ... TraitValue 

etc 

Ho giocato con tavoli girevoli e sono riuscito a ottenere le colonne della tabella JobParamType, cercando in esempi e li segue, ma è ora ottenere abbastanza complicato perché la mia tecnica è diviso tra diversi tavoli e sta iniziando a farmi male alla testa !!!

DECLARE @cols NVARCHAR(MAX) 
SELECT @cols = STUFF((SELECT DISTINCT TOP 10 PERCENT 
           '],[' + tParams.Name 
         FROM dbo.JobParamType AS tParams 
         ORDER BY '],[' + tParams.Name 
         FOR XML PATH('') 
        ), 1, 2, '') + ']' 
print @cols 

Spero che qualcuno possa aiutarmi con il pivoting e ottenere i dati da più tabelle.

Spero che questo abbia senso e attendo con impazienza il vostro aiuto e le vostre discussioni.

Grazie in anticipo.

risposta

8

Inserirò alcuni esempi da this model - perché li ho già. Entrambi i modelli sono molto simili, quindi non dovresti avere troppi problemi adottando questa tecnica.

Quando si tratta di mal di testa, trovo che il modo più semplice sia quello di procedere passo dopo passo e ottimizzare in seguito.

Fase 1.
Creare una vista per appiattire il modello; (see the model)

CREATE VIEW dbo.vProperties AS 
SELECT m.MachineID AS [Machine ID] 
,s.SetupID AS [Setup ID] 
,p.PropertyID AS [Property ID] 
,t.PropertyTypeID AS [Property Type ID] 
,m.Name AS [Machine Name] 
,s.Name AS [Setup Name] 
,t.Name AS [Property Type Name] 
,t.IsTrait AS [Is Trait] 
,x.Value AS [Measurement Value] 
,x.Unit AS [Unit] 
,y.Value AS [Trait] 
FROM dbo.Machine AS m 
JOIN dbo.Setup AS s ON s.MachineID = m.MachineID 
JOIN dbo.Property AS p ON p.SetupID = s.SetupID 
JOIN dbo.PropertyType AS t ON t.PropertyTypeID = p.PropertyTypeID 
LEFT JOIN dbo.Measurement AS x ON x.PropertyID = p.PropertyID 
LEFT JOIN dbo.Trait AS y ON y.PropertyID = p.PropertyID 

Fase 2.

Creare una vista per generare solo [Setup Name], [Property Type Name], [Value]; si noti che in questo il valore di misura e il tratto finiscono nella stessa colonna. Si sarebbe probabilmente utilizzare JobName, ParameterTypeName, Value

CREATE VIEW dbo.vSetupValues AS 
SELECT [Setup Name] 
     ,[Property Type Name] 
     ,COALESCE(cast([Measurement Value] AS varchar(50)), [Trait]) AS [Val] 
FROM dbo.vProperties 

Fase 3.

Crea elenco delle proprietà (parametri) con una colonna per ordinare da

DECLARE @Props TABLE (
id int IDENTITY (1,1) 
,PropName varchar(50) 
); 

INSERT INTO @Props (PropName) 
SELECT DISTINCT [Name] 
FROM dbo.PropertyType 

Fase 4.

Ora vi dinamicamente creare il testo della query

DECLARE @qw TABLE(
id int IDENTITY (1,1) 
, txt nchar(500) 
) 

INSERT INTO @qw (txt) 
    SELECT 'SELECT' UNION 
    SELECT '[Setup Name]' ; 

INSERT INTO @qw (txt) 
    SELECT ',MAX(CASE [Property Type Name] WHEN ''' + PropName 
    + ''' THEN Val ELSE NULL END) AS [' + PropName + ']' 
    FROM @Props 
    ORDER BY id; 

INSERT INTO @qw (txt) 
SELECT 'FROM dbo.vSetupValues' UNION 
SELECT 'GROUP BY [Setup Name]' UNION 
SELECT 'ORDER BY [Setup Name]'; 

Fase 5.

E qui è il testo della query, da questo punto posso impacchettarlo in una stored procedure, un'altra vista, o in una variabile da usare come SQL dinamico.

SELECT txt FROM @qw 

rendimenti

SELECT                                                                                                                            
[Setup Name]                                                                                                                           
,MAX(CASE [Property Type Name] WHEN 'Diameter LSL' THEN [Val] ELSE NULL END) AS [Diameter LSL]                                                                                                      
,MAX(CASE [Property Type Name] WHEN 'Diameter USL' THEN [Val] ELSE NULL END) AS [Diameter USL]                                                                                                      
,MAX(CASE [Property Type Name] WHEN 'Force LSL' THEN [Val] ELSE NULL END) AS [Force LSL]                                                                                                        
,MAX(CASE [Property Type Name] WHEN 'Force USL' THEN [Val] ELSE NULL END) AS [Force USL]                                                                                                        
,MAX(CASE [Property Type Name] WHEN 'Leak LSL' THEN [Val] ELSE NULL END) AS [Leak LSL]                                                                                                        
,MAX(CASE [Property Type Name] WHEN 'Leak USL' THEN [Val] ELSE NULL END) AS [Leak USL]                                                                                                        
,MAX(CASE [Property Type Name] WHEN 'Press Travel LSL' THEN [Val] ELSE NULL END) AS [Press Travel LSL]                                                                                                    
,MAX(CASE [Property Type Name] WHEN 'Press Travel USL' THEN [Val] ELSE NULL END) AS [Press Travel USL]                                                                                                    
,MAX(CASE [Property Type Name] WHEN 'Seal Height LSL' THEN [Val] ELSE NULL END) AS [Seal Height LSL]                                                                                                     
,MAX(CASE [Property Type Name] WHEN 'Seal Height USL' THEN [Val] ELSE NULL END) AS [Seal Height USL]                                                                                                     
FROM dbo.vSetupValues                                                                                                                        
GROUP BY [Setup Name]                                                                                                                        
ORDER BY [Setup Name]          

E se corro questo:
alt text http://www.damirsystems.com/dp_images/machinesetup_results.png


UPDATE: bug fisso al punto 4, è stato Max mancante() e ha aggiunto risultati esempio.

+0

Grazie ... il tuo tempo e gli sforzi sono molto apprezzati. Un po 'più complicato di prima, anche se questo compito sarebbe così, passerò il tuo esempio oggi e lo suddividerò in passaggi. – Belliez

+0

Damir, sei un genio, grazie. Funziona perfettamente. Solo un'ultima domanda. Come potrei eseguire questo comando come hai sopra. Passaggio 5 "SELEZIONA txt FROM @qw" visualizza il comando in una tabella (tramite SQL Management Studio) e devo copiarlo e incollarlo in una nuova query. Ancora grazie, – Belliez

+0

L'idea è di "impacchettare" la query finale in una vista, una procedura o una variabile, a seconda della frequenza con cui può cambiare l'elenco dei parametri. Se quei 400 parametri cambiano poche volte all'anno, usa la visualizzazione e costruisci le modifiche manualmente. Se cambiano ogni giorno, inseriscilo in una variabile ed esegui come SQL dinamico, automatizza anche i passaggi 3 e 4. –