创建具有动态行和列的数据透视-sql server 2016

jdg4fx2g  于 2021-08-09  发布在  Java
关注(0)|答案(1)|浏览(391)

首先,让我们定义表:

  1. CREATE TABLE dbo.Reviews (
  2. id int IDENTITY(1,1) NOT NULL PRIMARY KEY,
  3. reviewer char(64) NOT NULL,
  4. reviewee char(64) NOT NULL,
  5. review_date datetime NOT NULL,
  6. )
  7. CREATE TABLE dbo.Questions (
  8. id int IDENTITY(1,1) NOT NULL PRIMARY KEY,
  9. question_name varchar(255) NOT NULL,
  10. question_description varchar(500) NOT NULL,
  11. input_type_id int NOT NULL,
  12. option_group_id INT NULL
  13. )
  14. CREATE TABLE dbo.Input_Types (
  15. id int IDENTITY(1,1) NOT NULL PRIMARY KEY,
  16. input_type_name varchar(80) NOT NULL
  17. )
  18. CREATE TABLE dbo.Option_Groups (
  19. id int IDENTITY(1,1) NOT NULL PRIMARY KEY,
  20. option_group_name varchar(45) NOT NULL
  21. )
  22. CREATE TABLE dbo.Option_Choices (
  23. id int IDENTITY(1,1) NOT NULL PRIMARY KEY,
  24. option_group_id int NOT NULL,
  25. option_choice_name varchar(45) NULL,
  26. option_choice_value int NULL
  27. )
  28. CREATE TABLE dbo.Answers (
  29. id int IDENTITY(1,1) NOT NULL PRIMARY KEY,
  30. review_id int NOT NULL,
  31. question_id int NULL,
  32. answer_numeric int NULL,
  33. answer_text varchar(max) NULL,
  34. answer_yn bit NULL
  35. )
  36. ALTER TABLE Answers WITH CHECK ADD FOREIGN KEY(question_id) REFERENCES Questions (id)
  37. ALTER TABLE Answers WITH CHECK ADD FOREIGN KEY(review_id) REFERENCES Reviews (id)
  38. ALTER TABLE Option_Choices WITH CHECK ADD FOREIGN KEY(option_group_id) REFERENCES Option_Groups (id)
  39. ALTER TABLE Questions WITH CHECK ADD FOREIGN KEY(input_type_id) REFERENCES Input_Types (id)
  40. ALTER TABLE Questions WITH CHECK ADD FOREIGN KEY(option_group_id) REFERENCES Option_Groups (id)

以下查询获取特定被审核人的所有答案和问题:

  1. SELECT r.review_date, s1.q_id, s1.question_description, s1.answer_numeric
  2. FROM Reviews r
  3. LEFT JOIN (SELECT a.review_id, q.id q_id ,q.question_description, a.answer_numeric
  4. FROM Answers a
  5. LEFT JOIN Questions q
  6. ON a.question_id=q.id
  7. WHERE a.answer_numeric IS NOT NULL
  8. AND a.question_id IS NOT NULL) s1
  9. ON r.id=s1.review_id
  10. WHERE r.reviewee = 'SOMEUNIQUEIDGOESHERE'

输出大致如下:

  1. review_date q_id question_description answer_numeric
  2. -----------------------------------------------------------------
  3. 2020-06-15 09:59:21.677 27 Role models blah 2
  4. 2020-06-15 09:59:21.677 29 Looks for blah 3
  5. 2020-06-15 09:59:21.677 30 Consistently blah 2
  6. 2020-06-26 13:58:58.420 27 Role models blah 5
  7. 2020-06-26 13:58:58.420 29 Looks for blah 4
  8. 2020-06-26 13:58:58.420 30 Consistently blah 4

我想要的是这样的输出:

  1. q_id question_description 2020-06-15 2020-06-26
  2. ---------------------------------------------------
  3. 27 Role models blah 2 5
  4. 29 Looks for blah 3 4
  5. 30 Consistently blah 2 4

问题和评论/评论的数量直到运行时才知道。
我最终将为vb/asp前端编写这个查询,因此如果通过vb处理一些动态信息更容易,那是可行的。它不一定是一个纯粹的sql解决方案。
编辑我尝试了以下查询:

  1. DECLARE @cols AS VARCHAR(MAX), @query AS VARCHAR(MAX)
  2. SELECT @cols = STUFF((SELECT ',', QUOTENAME(review_date) FROM Reviews WHERE reviewee = '9AA1D3BAE1E0A9FA27B4857992548665C252931263B4D407CA8BBF21DC08D800' FOR XML PATH (''), TYPE).value('.', 'VARCHAR(MAX)'),1,1,'')
  3. SET @query = 'SELECT q_id, question_description, ' + @cols + ' FROM
  4. (SELECT r.review_date, s1.q_id, s1.question_description, s1.answer_numeric
  5. FROM Reviews r
  6. LEFT JOIN (SELECT a.review_id, q.id q_id ,q.question_description, a.answer_numeric
  7. FROM Answers a
  8. LEFT JOIN Questions q
  9. ON a.question_id=q.id
  10. WHERE a.answer_numeric IS NOT NULL
  11. AND a.question_id IS NOT NULL) s1
  12. ON r.id=s1.review_id
  13. WHERE r.reviewee = ''UNIQUEIDGOESHERE''
  14. ) x
  15. PIVOT
  16. (
  17. SUM(answer_numeric)
  18. FOR review_date IN (' + @cols + ')
  19. ) P
  20. ORDER BY q_id'
  21. execute(@query);

它创建了正确的列,但日期列中的结果为null

ax6ht2ek

ax6ht2ek1#

好吧,最后一个查询结果是正确的,问题是从quotename隐式发生的自动日期到字符串转换导致in子句中没有匹配项。
最终正确查询:

  1. DECLARE @cols AS VARCHAR(MAX), @query AS VARCHAR(MAX)
  2. SELECT @cols = STUFF((SELECT ',', QUOTENAME(FORMAT(review_date, 'dd-MMM-yyyy')) FROM Reviews WHERE reviewee = '9AA1D3BAE1E0A9FA27B4857992548665C252931263B4D407CA8BBF21DC08D800' FOR XML PATH (''), TYPE).value('.', 'VARCHAR(MAX)'),1,1,'')
  3. SET @query = 'SELECT q_id, question_description, ' + @cols + ' FROM
  4. (SELECT FORMAT(r.review_date, ''dd-MMM-yyyy'') rd, s1.q_id, s1.question_description, s1.answer_numeric
  5. FROM Reviews r
  6. LEFT JOIN (SELECT a.review_id, q.id q_id ,q.question_description, a.answer_numeric
  7. FROM Answers a
  8. LEFT JOIN Questions q
  9. ON a.question_id=q.id
  10. WHERE a.answer_numeric IS NOT NULL
  11. AND a.question_id IS NOT NULL) s1
  12. ON r.id=s1.review_id
  13. WHERE r.reviewee = ''UNIQUEIDGOESHERE''
  14. ) x
  15. PIVOT
  16. (
  17. SUM(answer_numeric)
  18. FOR rd IN (' + @cols + ')
  19. ) P
  20. ORDER BY q_id'
  21. execute(@query);
展开查看全部

相关问题