Швидкий сюжет, ми працюємо з зовнішнім постачальником, який має систему опитування. Система не обов'язково розроблена найкраще, коли створюється нове опитування, і система створює нову таблицю, тобто:
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)
Таблиці генеруються з назвою SurveyId
в кінці імені ( Library_
), а стовпці "Питання" створюються з QuestionId
в кінці його ( Q_
). Для уточнення, запитання зберігаються в окремій таблиці, тому в той час як ідентифікатори запитань є послідовними, вони не починаються з 1 для кожного опитування. Стовпці запитань базуватимуться на ідентифікаторі, призначеному їм у таблиці.
Здається, достатньо простого запиту, за винятком того, що нам потрібно витягнути дані з усіх таблиць опитування для надсилання в іншу систему, і ось звідки виникає проблема. Оскільки таблиці створюються автоматично, коли нове опитування додається передньою панеллю, З іншого боку, система не може обробляти цей тип структури. Їм необхідні дані, щоб вони були послідовними для споживання.
Тому мені було доручено написати збережену процедуру, яка витягне дані з усіх таблиць опитування та розмістить їх у наступному форматі:
SurveyId InstanceId QNumber Response
________ __________ _______ ________
1 1 1 great
1 2 1 the best
2 9 2 10
3 50 50 test
Маючи дані для всіх таблиць в одному форматі, їх може споживати кожен, незалежно від кількості таблиць та питань опитування.
Я написав збережену процедуру, яка, здається, працює, але мені цікаво, чи я щось пропускаю, чи є кращий спосіб впоратися з таким типом ситуації.
Мій код:
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)
Я створив SQL Fiddle з деякими зразками даних та кодом.
Чи є інший спосіб написання цього типу запиту? Чи є з цим помітні проблеми?
На жаль, з цим існує багато невідомих ... скільки таблиць у нас буде і скільки запитань за опитування. Я б сказав, що у нас буде від 25 до 50 опитувань, по 2–5 питань у кожному.