Trasporre un set di righe come colonne in SQL Server 2000
-
02-07-2019 - |
Domanda
Esiste la possibilità di trasporre le righe in colonne in SQL Server (è possibile in MS-Access)? Ero confuso perché questa funzione è disponibile in MS-Access ma non in SQL Server. È di progettazione che questa funzionalità non è stata inclusa in SQL Server?
Soluzione
color red
size big
city Chicago
Descriverò una tecnica che funziona. L'ho usato. NON lo sto promuovendo, ma funziona.
Per ruotare i dati laddove non si conoscono i valori in anticipo, creare una tabella temporanea al volo senza colonne. Quindi utilizza un cursore per scorrere tra le tue righe, emettendo una tabella di modifica "quot" modificata in modo dinamico " per ogni variabile, in modo che alla fine la tua tabella temporanea abbia le colonne, il colore, le dimensioni, la città.
Quindi inserisci una riga nella tabella temporanea, la aggiorni tramite un altro cursore attraverso la variabile, le coppie di valori, e poi la selezioni, di solito unita con la sua entità padre, in effetti facendo sembrare che quelle coppie variabili / valore personalizzate fossero come colonne incorporate nell'entità genitore originale.
Altri suggerimenti
Il metodo del cursore descritto è probabilmente il meno simile a SQL da usare. Come accennato, SQL 2005 e successivi ha PIVOT che funziona alla grande. Ma per versioni precedenti e server non MS SQL, il metodo Rozenshtein da "Ottimizzazione di Transact-SQL" (modifica: esaurito, ma disponibile da Amazon: http: //www.amazon .com / Optimizing-Transact-SQL-Advanced-Programming-Techniques / dp / 0964981203 ), è eccellente per i dati pivotanti e non pivotanti. Utilizza le caratteristiche dei punti per trasformare i dati basati su righe in colonne. Rozenshtein descrive diversi casi, ecco un esempio:
SELECT
RowValueNowAColumn =
CONVERT(varchar,
MAX(
SUBSTRING(myTable.MyVarCharColumn,1,DATALENGTH(myTable.MyVarCharColumn)
* CHARINDEX(sa.SearchAttributeName,'MyRowValue'))))
FROM
myTable
Questo metodo è molto più efficiente rispetto all'utilizzo delle istruzioni case e funziona con una varietà di tipi di dati e implementazioni SQL (non solo MS SQL).
Meglio limitare su piccola scala per questo genere di cose. Se stai usando SQL 2k e non hai le funzionalità PIVOT disponibili, ho redatto un proc memorizzato che dovrebbe fare il lavoro per te. Un po 'di fretta, quindi fatelo a pezzi quanto volete. Incolla il sotto in una finestra sql e modifica EXEC in basso come preferisci. Se vuoi vedere cosa viene generato, rimuovi il --s nel mezzo:
IF EXISTS (SELECT * FROM SYSOBJECTS WHERE XTYPE = 'P' AND NAME = 'USP_LIST_CONCAT')
DROP PROCEDURE USP_LIST_CONCAT
GO
CREATE PROCEDURE USP_LIST_CONCAT (@SourceTable NVARCHAR(1000) = '' ,@SplitColumn NVARCHAR(1000) = '' , @Deli NVARCHAR(10) = '', @KeyColumns NVARCHAR(2000) = '' , @Condition NVARCHAR(1000) = '')
AS
BEGIN
SET NOCOUNT ON
/* PROCEDURE CREATED 2010 FOR SQL SERVER 2000. SIMON HUGHES. */
/* NOTES: REMOVE --'s BELOW TO LIST GENERATED SQL. */
IF @SourceTable = '' OR @SourceTable = '?' OR @SourceTable = '/?' OR @SplitColumn = '' OR @KeyColumns = ''
BEGIN
PRINT 'Format for use:'
PRINT ' USP_LIST_CONCAT ''SourceTable'', ''SplitColumn'', ''Deli'', ''KeyColumn1,...'', ''Column1 = 12345 AND ...'''
PRINT ''
PRINT 'Description:'
PRINT 'The SourceTable should contain a number of records acting as a list of values.'
PRINT 'The SplitColumn should be the name of the column holding the values wanted.'
PRINT 'The Delimiter may be any single character or string ie ''/'''
PRINT 'The KeyColumn may contain a comma separated list of columns that will be returned before the concatenated list.'
PRINT 'The optional Conditions may be left blank or may include the following as examples:'
PRINT ' ''Column1 = 12334 AND (Column2 = ''ABC'' OR Column3 = ''DEF'')'''
PRINT ''
PRINT 'A standard list in the format:'
PRINT ' Store1, Employee1, Rabbits'
PRINT ' Store1, Employee1, Dogs'
PRINT ' Store1, Employee1, Cats'
PRINT ' Store1, Employee2, Dogs'
PRINT ''
PRINT 'Will be returned as:'
PRINT ' Store1, Employee1, Cats/Dogs/Rabbits'
PRINT ' Store1, Employee2, Dogs'
PRINT ''
PRINT 'A full ORDER BY and DISTINCT is included'
RETURN -1
END
DECLARE @SQLStatement NVARCHAR(4000)
SELECT @SQLStatement = '
DECLARE @DynamicSQLStatement NVARCHAR(4000)
SELECT @DynamicSQLStatement = ''SELECT '+@KeyColumns+', SUBSTRING(''
SELECT @DynamicSQLStatement = @DynamicSQLStatement + '' + '' + CHAR(10) +
'' MAX(CASE WHEN '+@SplitColumn+' = ''''''+RTRIM('+@SplitColumn+')+'''''' THEN '''''+@Deli+'''+RTRIM('+@SplitColumn+')+'''''' ELSE '''''''' END)''
FROM '+ @SourceTable +' ORDER BY '+@SplitColumn+'
SELECT @DynamicSQLStatement = @DynamicSQLStatement + '' ,2,7999) List'' + CHAR(10) + ''FROM '+ @SourceTable+''' + CHAR(10) +'''+CASE WHEN @Condition = '' THEN '/* WHERE */' ELSE 'WHERE '+@Condition END+ '''+ CHAR(10) + ''GROUP BY '+@KeyColumns+'''
SELECT @DynamicSQLStatement = REPLACE(@DynamicSQLStatement,''( +'',''('')
-- SELECT @DynamicSQLStatement -- DEBUG ONLY
EXEC (@DynamicSQLStatement)'
EXEC (@SQLStatement)
END
GO
EXEC USP_LIST_CONCAT 'MyTableName', 'ColumnForListing', 'Delimiter', 'KeyCol1, KeyCol2', 'Column1 = 123456'
Per UNPIVOT in SQL Server 2005, ho trovato un buon articolo
Ho i dati nel seguente formato
Survey_question_ID
Email (utente )
risposta ??strong>
per 1 sondaggio ci sono 13 domande e risposte l'output desiderato che volevo era
Utente --- Survey_question_ID1 --- Survey_question_ID2
email --- risposte --- rispondi ........ ecc.
Ecco la soluzione per SQL Server 2000 , il tipo di dati del campo Cause è TESTO .
DROP TABLE #tmp
DECLARE @tmpTable TABLE
(
emailno NUMERIC,
question1 VARCHAR(80),
question2 VARCHAR(80),
question3 VARCHAR(80),
question4 VARCHAR(80),
question5 VARCHAR(80),
question6 VARCHAR(80),
question7 VARCHAR(80),
question8 VARCHAR(80),
question9 VARCHAR(80),
question10 VARCHAR(80),
question11 VARCHAR(80),
question12 VARCHAR(80),
question13 VARCHAR(8000)
)
DECLARE @tmpTable2 TABLE
(
emailNumber NUMERIC
)
DECLARE @counter INT
DECLARE @Email INT
SELECT @counter =COUNT(DISTINCT ans.email) FROM answers ans WHERE ans.surveyname=100430 AND ans.qnpkey BETWEEN 233702 AND 233714
SELECT * INTO #tmp FROM @tmpTable
INSERT INTO @tmpTable2 (emailNumber) SELECT DISTINCT CAST(ans.email AS NUMERIC) FROM answers ans WHERE ans.surveyname=100430 AND ans.qnpkey BETWEEN 233702 AND 233714
WHILE @counter >0
BEGIN
SELECT TOP 1 @Email= emailNumber FROM @tmpTable2
INSERT INTO @tmpTable (emailno) VALUES (@Email )
Update @tmpTable set question1=CAST(answer as VARCHAR(80)) from answers ans where ans.surveyname=100430 and ans.qnpkey = 233702 and ans.email=@Email
Update @tmpTable set question2=CAST(answer as VARCHAR(80)) from answers ans where ans.surveyname=100430 and ans.qnpkey = 233703 and email=@email
Update @tmpTable set question3=CAST(answer as VARCHAR(80)) from answers ans where ans.surveyname=100430 and ans.qnpkey = 233704 and email=@email
Update @tmpTable set question4=CAST(answer as VARCHAR(80)) from answers ans where ans.surveyname=100430 and ans.qnpkey = 233705 and email=@email
Update @tmpTable set question5=CAST(answer as VARCHAR(80)) from answers ans where ans.surveyname=100430 and ans.qnpkey = 233706 and email=@email
Update @tmpTable set question6=CAST(answer as VARCHAR(80)) from answers ans where ans.surveyname=100430 and ans.qnpkey = 233707 and email=@email
Update @tmpTable set question7=CAST(answer as VARCHAR(80)) from answers ans where ans.surveyname=100430 and ans.qnpkey = 233708 and email=@email
Update @tmpTable set question8=CAST(answer as VARCHAR(80)) from answers ans where ans.surveyname=100430 and ans.qnpkey = 233709 and email=@email
Update @tmpTable set question9=CAST(answer as VARCHAR(80)) from answers ans where ans.surveyname=100430 and ans.qnpkey = 233710 and email=@email
Update @tmpTable set question10=CAST(answer as VARCHAR(80)) from answers ans where ans.surveyname=100430 and ans.qnpkey = 233711 and email=@email
Update @tmpTable set question11=CAST(answer as VARCHAR(80)) from answers ans where ans.surveyname=100430 and ans.qnpkey = 233712 and email=@email
Update @tmpTable set question12=CAST(answer as VARCHAR(80)) from answers ans where ans.surveyname=100430 and ans.qnpkey = 233713 and email=@email
Update @tmpTable set question13=CAST(answer as VARCHAR(8000)) from answers ans where ans.surveyname=100430 and ans.qnpkey = 233714 and email=@email
insert into #tmp select * from @tmpTable
DELETE FROM @tmpTable
DELETE FROM @tmpTable2 WHERE emailNumber= @Email
set @counter =@counter -1
End
select * from #tmp