Hızlı bir hikaye, bir anket sistemi olan bir dış satıcı ile çalışıyoruz. Sistem yeni bir anket oluşturduğunuzda ve sistem yeni bir tablo oluşturduğunuzda, yani:
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)
Tablolar SurveyId
adın sonunda ( Library_
) ile, Soru sütunları da QuestionId
sonunda ( Q_
) ile oluşturulur. Açıklığa kavuşturmak için, sorular ayrı bir tabloda saklanır, böylece soru kimlikleri sıralı olsa da, her anket için 1'den başlamazlar. Soru sütunları, tabloda kendilerine atanan kimliği temel alacaktır.
Başka bir sisteme gönderilecek tüm anket tablolarından verileri çıkarmamız gerektiği ve sorunun devreye girdiği yer dışında sorgulamak için yeterince basit görünüyor. Ön taraf tarafından yeni bir anket eklendiğinde tablolar otomatik olarak oluşturulduğundan diğer sistem bu tür yapıları işleyemez. Verilerin tüketebilmeleri için tutarlı olmaları gerekir.
Bu yüzden tüm Anket tablolarından veri ayıklayıp aşağıdaki biçimde yerleştirecek saklı bir yordam yazmakla görevlendirildim:
SurveyId InstanceId QNumber Response
________ __________ _______ ________
1 1 1 great
1 2 1 the best
2 9 2 10
3 50 50 test
Tüm tablolara ilişkin verilerin aynı formatta olması, kaç anket tablosu ve sorusu olursa olsun herkes tarafından tüketilebilir.
Çalışıyor gibi görünen bir saklı yordam yazdım ama bir şey eksik olup olmadığımı veya bu tür bir durumla başa çıkmanın daha iyi bir yolu olup olmadığını merak ediyorum.
Kodum:
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)
Bazı örnek veriler ve kod ile bir SQL Fiddle oluşturduk .
Bu tür bir sorgu yazmanın farklı bir yolu var mı? Bununla ilgili belirgin sorunlar var mı?
Ne yazık ki, bununla ilgili birçok bilinmeyen var ... kaç masaya sahip olacağız ve anket başına kaç soru var. Her biri 2-5 sorudan oluşan 25-50 anketimiz olacağını söyleyebilirim.