2015-08-06 12 views
5

spiegazionePivot duplicare i nomi delle colonne e ottenere tutti i valori per le colonne

Immaginate che io ho 2 tabelle. FormFields dove vengono memorizzati i nomi delle colonne come valori, che devono essere ruotati e la seconda tabella FilledValues con i valori inseriti dall'utente con FormFieldId fornito.

PROBLEMA

Come potete vedere (qui sotto nella sezione CAMPIONE) in FormFields tabella ho i nomi duplicati, ma ID diverso di. Devo farlo dopo aver unito le tabelle, tutti i valori della tabella FilledValues verranno assegnati ai nomi delle colonne, non a quelli dell'I.

Quello che mi serve meglio lo vedrete nella sezione OUTPUT qui sotto.

DATI CAMPIONE

FormFields

ID Name GroupId 
1 col1  1 
2 col2  1 
3 col3  1 
4 col1  2 
5 col2  2 
6 col3  2 

FilledValues

ID Name FormFieldId GroupID 
1  a  2   1 
2  b  3   1 
3  c  1   1 
4  d  4   2 
5  e  6   2 
6  f  5   2 

USCITA PER ORA

col1 col2 col3 
c  a  b -- As you see It returning only values for FormFieldId 1 2 3 
        -- d, e, f are lost that because It have duplicate col names, but different id's 

uscita desiderata

col1 col2 col3 
c  a  b 
e  f  d 

QUERY

SELECT * FROM 
(
    SELECT FF.Name AS NamePiv, 
      FV.Name AS Val1  
    FROM FormFields FF 
    JOIN FilledValues FV ON FF.Id = FV.FormFieldId  
) x 
PIVOT 
(
    MIN(Val1) 
    FOR NamePiv IN ([col1],[col2],[col3]) 
) piv 

SQL FIDDLE

Come posso produrre l'output con il più righe?

risposta

2

Dal momento che si sta utilizzando PIVOT i dati vengono aggregati in modo da restituire un solo valore per ogni colonna essere raggruppate. Non ci sono colonne nella sottoquery che sono univoche e vengono utilizzate nell'aspetto di raggruppamento di PIVOT per restituire più righe. Per fare questo hai bisogno di un certo valore. Se si dispone di una colonna con un valore univoco per ciascun "gruppo", la si utilizzerà o si può utilizzare una funzione di finestratura come row_number().

row_number() creerà un numero sequenziale per ogni FF.Name significato se si dispone di 2 col1 si genererà un 1 per una riga e una 2 per un'altra riga.Una volta che questo è incluso nel vostro sottoquery, ora avete un valore univoco che viene utilizzato quando l'aggregazione dei dati e si tornerà più righe:

SELECT [col1],[col2],[col3] 
FROM 
(
    SELECT 
    FF.Name AS NamePiv, 
    FV.Name AS Val1, 
    rn = row_number() over(partition by ff.Name order by fv.Id) 
    FROM FormFields FF 
    JOIN FilledValues FV ON FF.Id = FV.FormFieldId   
) x 
PIVOT 
(
    MIN(Val1) 
    FOR NamePiv IN ([col1],[col2],[col3]) 
) piv; 

Vedi SQL Fiddle with Demo. L'output è:

| col1 | col2 | col3 | 
|------|------|------| 
| c | a | b | 
| e | f | d | 
+0

Grazie per la risposta, c'è un piccolo problema in alcuni 'Gruppi' sono tutti i valori di FormField vuoti (nessun valore), come posso evitare di selezionare queste righe? Ecco SQL Fiddle, aggiunto GroupId 3 con tutti i valori vuoti. Questa riga non deve essere selezionata: http://sqlfiddle.com/#!3/2961a/1 –

+0

@ StanislovasKalašnikovas Utilizzare una clausola where per filtrare gli spazi vuoti 'FilledValues' - http://sqlfiddle.com/#!3/2961a/3 – Taryn

2

Solo l'aggiunta di GroupId in Pivot source interrogazione risolverà il vostro problema

SELECT * FROM (
SELECT FF.Name AS NamePiv, 
     FV.Name AS Val1, 
     ff.groupid 
FROM FormFields FF 
JOIN FilledValues FV ON FF.Id = FV.FormFieldId  
) x 
PIVOT 
(
MIN(Val1) 
FOR NamePiv IN ([col1],[col2],[col3]) 
) piv 

SQLFIDDLE DEMO

+0

Grazie per la risposta, c'è un piccolo problema in alcuni 'Gruppi' sono tutti i valori di FormField vuoti (nessun valore), come posso evitare di selezionare queste righe? Ecco SQL Fiddle, aggiunto GroupId 3 con tutti i valori vuoti. Questa riga non deve essere selezionata: http://sqlfiddle.com/#!3/2961a/1 –

+0

@ StanislovasKalašnikovas - Il filtro semplice dovrebbe risolvere il problema http://sqlfiddle.com/#!3/2961a/2 o basato sul requisito estendere il filtro –

0

sarei propenso a che fare questo con l'aggregazione condizionale:

select max(case when formfieldid % 3 = 1 then name end) as col1, 
     max(case when formfieldid % 3 = 2 then name end) as col2, 
     max(case when formfieldid % 3 = 0 then name end) as col3 
from FilledValues 
group by GroupID; 

Non è chiaro quale la regola è per assegnare un valore a una colonna. Questo utilizza il resto, che funziona per i dati di input.