Breve storia, stiamo lavorando con un fornitore esterno che ha un sistema di sondaggi. Il sistema non è necessariamente progettato in modo ottimale quando si crea un nuovo sondaggio e il sistema crea una nuova tabella, ovvero:
Tables
____
Library_1 -- table for Survey 1
SurveyId int
InstanceId int
Q_1 varchar(50)
Library_2 -- table for Survey 2
SurveyId int
InstanceId int
Q_2 int
Q_3 int
Q_4 varchar(255)
Le tabelle vengono generate con il SurveyId
alla fine del nome ( Library_
) e le colonne Domanda vengono generate con il QuestionId
alla fine del nome ( Q_
). Per chiarire, le domande sono memorizzate in una tabella separata, quindi mentre gli ID delle domande sono sequenziali, non iniziano da 1 per ogni sondaggio. Le colonne delle domande si baseranno sull'ID assegnato loro nella tabella.
Sembra abbastanza semplice da interrogare, tranne per il fatto che è necessario estrarre i dati da tutte le tabelle dei sondaggi per essere inviati a un altro sistema ed è qui che si presenta il problema. Poiché le tabelle vengono create automaticamente quando un nuovo sondaggio viene aggiunto dal front- fine dell'applicazione, l'altro sistema non è in grado di gestire questo tipo di struttura. Hanno bisogno che i dati siano coerenti perché possano consumarli.
Quindi mi è stato assegnato il compito di scrivere una procedura memorizzata che estrarrà i dati da tutte le tabelle dei sondaggi e li posizionerà nel seguente formato:
SurveyId InstanceId QNumber Response
________ __________ _______ ________
1 1 1 great
1 2 1 the best
2 9 2 10
3 50 50 test
Avendo i dati per tutte le tabelle nello stesso formato, possono essere consumati da chiunque, indipendentemente dal numero di tabelle e domande dell'indagine.
Ho scritto una procedura memorizzata che sembra funzionare ma mi chiedo se mi manca qualcosa o se esiste un modo migliore per gestire questo tipo di situazione.
Il mio codice:
declare @sql varchar(max) = ''
declare @RowCount int = 1
declare @TotalRecords int = (SELECT COUNT(*) FROM SurveyData)
Declare @TableName varchar(50) = ''
Declare @ColumnName varchar(50) = ''
WHILE @RowCount <= @TotalRecords
BEGIN
SELECT @TableName = tableName, @ColumnName = columnName
FROM SurveyData
WHERE @RowCount = rownum
SET @sql = @sql +
' SELECT s.SurveyId
, s.InstanceId
, CASE WHEN columnName = ''' + @ColumnName + ''' THEN REPLACE(columnName, ''Q_'', '''') ELSE '''' END as QuestionNumber
, Cast(s.' + @ColumnName + ' as varchar(1000)) as ''Response''
FROM SurveyData t
INNER JOIN ' + @TableName + ' s' +
' ON REPLACE(t.tableName, ''Library_'', '''') = s.SurveyID ' +
' WHERE t.columnName = ''' + @ColumnName + ''''
IF @RowCount != @TotalRecords
BEGIN
set @sql = @sql + ' UNION ALL'
END
SET @RowCount = @RowCount + 1
END
exec(@sql)
Ho creato un violino SQL con alcuni dati di esempio e il codice.
Esiste un modo diverso di scrivere questo tipo di query? Ci sono problemi evidenti con esso?
Sfortunatamente, ci sono molte incognite con questo ... quanti tavoli avremo e quante domande per sondaggio. Direi che avremo tra 25-50 sondaggi, con 2-5 domande ciascuno.