Câu chuyện nhanh trở lại, chúng tôi đang làm việc với một nhà cung cấp bên ngoài có hệ thống khảo sát. Hệ thống không nhất thiết phải được thiết kế tốt nhất ở chỗ khi bạn tạo một khảo sát mới và hệ thống tạo một bảng mới, nghĩa là:
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)
Các bảng được tạo với phần SurveyId
cuối của tên ( Library_
) và các cột Câu hỏi được tạo với QuestionId
phần cuối của nó ( Q_
). Để làm rõ, các câu hỏi được lưu trữ trong một bảng riêng vì vậy trong khi các id câu hỏi là tuần tự, chúng không bắt đầu từ 1 cho mỗi khảo sát. Các cột câu hỏi sẽ được dựa trên id được gán cho chúng trong bảng.
Có vẻ đủ đơn giản để truy vấn, ngoại trừ chúng ta cần trích xuất dữ liệu từ tất cả các bảng khảo sát được gửi đến một hệ thống khác và đây là nơi xảy ra sự cố. Vì các bảng được tạo tự động khi một khảo sát mới được thêm vào trước ứng dụng cuối, hệ thống khác không thể xử lý loại cấu trúc này. Họ cần dữ liệu phù hợp để họ tiêu thụ.
Vì vậy, tôi được giao nhiệm vụ viết một thủ tục được lưu trữ sẽ trích xuất dữ liệu từ tất cả các bảng Khảo sát và đặt nó theo định dạng sau:
SurveyId InstanceId QNumber Response
________ __________ _______ ________
1 1 1 great
1 2 1 the best
2 9 2 10
3 50 50 test
Bằng cách có dữ liệu cho tất cả các bảng ở cùng định dạng, sau đó bất kỳ ai cũng có thể sử dụng dữ liệu đó cho dù có bao nhiêu bảng khảo sát và câu hỏi tồn tại.
Tôi đã viết một thủ tục được lưu trữ có vẻ như đang hoạt động nhưng tôi tự hỏi liệu tôi có thiếu thứ gì không hoặc liệu có cách nào tốt hơn để xử lý loại tình huống này.
Mã của tôi:
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)
Tôi đã tạo SQL Fiddle với một số dữ liệu mẫu và mã.
Có một cách khác để loại truy vấn này nên được viết? Có bất kỳ vấn đề đáng chú ý với nó?
Thật không may, có rất nhiều điều chưa biết với điều này ... chúng ta sẽ có bao nhiêu bảng và bao nhiêu câu hỏi cho mỗi khảo sát. Tôi muốn nói rằng chúng tôi sẽ có từ 25-50 khảo sát, với 2-5 câu hỏi mỗi câu hỏi.