Kisah cepat kembali, kami bekerja dengan vendor luar yang memiliki sistem survei. Sistem tidak perlu dirancang yang terbaik ketika Anda membuat survei baru dan sistem membuat tabel baru, yaitu:
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)
Tabel dihasilkan dengan SurveyId
di akhir nama ( Library_
) dan kolom Pertanyaan dibuat dengan QuestionId
di akhir nama ( Q_
). Untuk memperjelas, pertanyaan disimpan dalam tabel terpisah sehingga sementara id pertanyaan berurutan mereka tidak mulai dari 1 untuk setiap survei. Kolom pertanyaan akan didasarkan pada id yang diberikan kepadanya dalam tabel.
Tampaknya cukup sederhana untuk di-query, kecuali kita perlu mengekstrak data dari semua tabel survei untuk dikirim ke sistem lain dan di sinilah masalahnya. Karena tabel dibuat secara otomatis ketika survei baru ditambahkan oleh front- aplikasi akhir, sistem lain tidak dapat menangani jenis struktur ini. Mereka membutuhkan data agar konsisten untuk dikonsumsi.
Jadi saya ditugaskan menulis prosedur tersimpan yang akan mengekstrak data dari semua tabel Survei dan menempatkannya dalam format berikut:
SurveyId InstanceId QNumber Response
________ __________ _______ ________
1 1 1 great
1 2 1 the best
2 9 2 10
3 50 50 test
Dengan memiliki data untuk semua tabel dalam format yang sama, maka dapat dikonsumsi oleh siapa pun tidak peduli berapa banyak tabel survei dan pertanyaan.
Saya menulis prosedur tersimpan yang tampaknya berfungsi tetapi saya bertanya-tanya apakah saya kehilangan sesuatu atau apakah ada cara yang lebih baik untuk menangani situasi semacam ini.
Kode saya:
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)
Saya telah membuat SQL Fiddle dengan beberapa sampel data dan kode.
Apakah ada cara lain untuk jenis kueri ini yang harus ditulis? Apakah ada masalah nyata dengan itu?
Sayangnya, ada banyak yang tidak diketahui dengan ini ... berapa banyak tabel yang akan kita miliki dan berapa banyak pertanyaan per survei. Saya akan mengatakan bahwa kita akan memiliki antara 25-50 survei, dengan 2-5 pertanyaan masing-masing.
Jawaban:
Berdasarkan komentar dari orang-orang dalam obrolan, saya memutuskan untuk mengubah skrip saya sedikit ke
INSERT INTO
tabel temp daripada membuat satu pernyataan SQL panjang untuk dieksekusi di akhir. Jadi pada akhirnya prosedur tersimpan saya berisi yang berikut:Lihat SQL Fiddle dengan skrip terakhir
sumber