Tsql 可怜人的SQL枢轴。以列形式列出问题,并在一行中列出每个用户的答案

Tsql 可怜人的SQL枢轴。以列形式列出问题,并在一行中列出每个用户的答案,tsql,Tsql,当前查询: 结果: 我如何正确地查询这些表,以获取如下所示的结果? 姓名和姓氏在一行上,列的问题和每列的答案 预期结果 这称为透视,其中行中的信息用于确定列列表。这种查询如果完全在查询中完成,则需要动态计算SQL,通常更适合客户端格式化。许多工具称之为透视或交叉表查询,SSRS称之为矩阵查询。这是MSSQL版本 select o.*, q1.[Type of Surgery:], q2.[Month of Surgery:], q3.[Year of surgery:] , q4.[Cu

当前查询:

结果:

我如何正确地查询这些表,以获取如下所示的结果? 姓名和姓氏在一行上,列的问题和每列的答案

预期结果


这称为透视,其中行中的信息用于确定列列表。这种查询如果完全在查询中完成,则需要动态计算SQL,通常更适合客户端格式化。许多工具称之为透视或交叉表查询,SSRS称之为矩阵查询。

这是MSSQL版本

select o.*, q1.[Type of Surgery:], q2.[Month of Surgery:], q3.[Year of surgery:]
    , q4.[Current Ostomy System Brand:]
    , q5.[Degree of Satisfaction with the fit and comfort of your Current Ostomy System:]
from (
    select distinct ordID, ordName + ' ' + ordLastName as [name] from dbo.Orders
) o
left join (
    select *, a.[Answer] as [Type of Surgery:] from cart_survey cs
    left join dbo.survey_answers a on cs.answer_id = a.id
    where cs.question_id = 1
) q1 on o.ordID = q1.[order_id]
left join (
    select *, a.[Answer] as [Month of Surgery:] from cart_survey cs
    left join dbo.survey_answers a on cs.answer_id = a.id
    where cs.question_id = 2
) q2 on o.ordID = q2.[order_id]
left join (
    select *, a.[Answer] as [Year of surgery:] from cart_survey cs
    left join dbo.survey_answers a on cs.answer_id = a.id
    where cs.question_id = 3
) q3 on o.ordID = q3.[order_id]
left join (
    select *, a.[Answer] as [Current Brand:] from cart_survey cs
    left join dbo.survey_answers a on cs.answer_id = a.id
    where cs.question_id = 4
) q4 on o.ordID = q4.[order_id]
left join (
    select *, a.[Answer] as [Degree of Satisfaction:] from cart_survey cs
    left join dbo.survey_answers a on cs.answer_id = a.id
    where cs.question_id = 5
) q5 on o.ordID = q5.[order_id]
SELECT o . * , 
q1.answer AS  'Type of Surgery:',
q2.answer AS  'Month of Surgery:',
q3.answer AS  'Year of Surgery:',
q4.answer AS  'Current Brand:',
q5.answer AS  'Degree of Satisfaction:'
FROM (
    SELECT DISTINCT ordID, ordName, ordLastName
    FROM orders
)o
LEFT JOIN (
    SELECT cs.order_id, a.answer
    FROM cart_survey cs
    LEFT JOIN survey_answers a ON cs.answer_id = a.id
    WHERE cs.question_id =18
)q1 ON o.ordID = q1.order_id
LEFT JOIN (
    SELECT cs.order_id, a.answer
    FROM cart_survey cs
    LEFT JOIN survey_answers a ON cs.answer_id = a.id
    WHERE cs.question_id =19
)q2 ON o.ordID = q2.order_id
LEFT JOIN (
    SELECT cs.order_id, a.answer
    FROM cart_survey cs
    LEFT JOIN survey_answers a ON cs.answer_id = a.id
    WHERE cs.question_id =20
)q3 ON o.ordID = q3.order_id
LEFT JOIN (
    SELECT cs.order_id, a.answer
    FROM cart_survey cs
    LEFT JOIN survey_answers a ON cs.answer_id = a.id
    WHERE cs.question_id =21
)q4 ON o.ordID = q4.order_id
LEFT JOIN (
    SELECT cs.order_id, a.answer
    FROM cart_survey cs
    LEFT JOIN survey_answers a ON cs.answer_id = a.id
    WHERE cs.question_id =22
)q5 ON o.ordID = q5.order_id

这是MySQL版本

select o.*, q1.[Type of Surgery:], q2.[Month of Surgery:], q3.[Year of surgery:]
    , q4.[Current Ostomy System Brand:]
    , q5.[Degree of Satisfaction with the fit and comfort of your Current Ostomy System:]
from (
    select distinct ordID, ordName + ' ' + ordLastName as [name] from dbo.Orders
) o
left join (
    select *, a.[Answer] as [Type of Surgery:] from cart_survey cs
    left join dbo.survey_answers a on cs.answer_id = a.id
    where cs.question_id = 1
) q1 on o.ordID = q1.[order_id]
left join (
    select *, a.[Answer] as [Month of Surgery:] from cart_survey cs
    left join dbo.survey_answers a on cs.answer_id = a.id
    where cs.question_id = 2
) q2 on o.ordID = q2.[order_id]
left join (
    select *, a.[Answer] as [Year of surgery:] from cart_survey cs
    left join dbo.survey_answers a on cs.answer_id = a.id
    where cs.question_id = 3
) q3 on o.ordID = q3.[order_id]
left join (
    select *, a.[Answer] as [Current Brand:] from cart_survey cs
    left join dbo.survey_answers a on cs.answer_id = a.id
    where cs.question_id = 4
) q4 on o.ordID = q4.[order_id]
left join (
    select *, a.[Answer] as [Degree of Satisfaction:] from cart_survey cs
    left join dbo.survey_answers a on cs.answer_id = a.id
    where cs.question_id = 5
) q5 on o.ordID = q5.[order_id]
SELECT o . * , 
q1.answer AS  'Type of Surgery:',
q2.answer AS  'Month of Surgery:',
q3.answer AS  'Year of Surgery:',
q4.answer AS  'Current Brand:',
q5.answer AS  'Degree of Satisfaction:'
FROM (
    SELECT DISTINCT ordID, ordName, ordLastName
    FROM orders
)o
LEFT JOIN (
    SELECT cs.order_id, a.answer
    FROM cart_survey cs
    LEFT JOIN survey_answers a ON cs.answer_id = a.id
    WHERE cs.question_id =18
)q1 ON o.ordID = q1.order_id
LEFT JOIN (
    SELECT cs.order_id, a.answer
    FROM cart_survey cs
    LEFT JOIN survey_answers a ON cs.answer_id = a.id
    WHERE cs.question_id =19
)q2 ON o.ordID = q2.order_id
LEFT JOIN (
    SELECT cs.order_id, a.answer
    FROM cart_survey cs
    LEFT JOIN survey_answers a ON cs.answer_id = a.id
    WHERE cs.question_id =20
)q3 ON o.ordID = q3.order_id
LEFT JOIN (
    SELECT cs.order_id, a.answer
    FROM cart_survey cs
    LEFT JOIN survey_answers a ON cs.answer_id = a.id
    WHERE cs.question_id =21
)q4 ON o.ordID = q4.order_id
LEFT JOIN (
    SELECT cs.order_id, a.answer
    FROM cart_survey cs
    LEFT JOIN survey_answers a ON cs.answer_id = a.id
    WHERE cs.question_id =22
)q5 ON o.ordID = q5.order_id

贴出的答案有效,但笨拙而缓慢。您可以执行我称之为并行聚合的操作:

SELECT
     ID,
     SUM(case when question_id = 1 then 1 else 0 end) as sum1,
     SUM(case when question_id = 2 then 1 else 0 end) as sum2,
     SUM(case when question_id = 3 then 1 else 0 end) as sum3
GROUP BY ID
这将在桌子上做一次传球,而不是三次,而且非常短。这不是一个完整的演练,但您肯定可以根据您的需要调整该概念。

这称为枢轴。使用静态版本或动态版本执行此操作有两种方法

静态版本是指将值硬编码为列:

SELECT *
FROM
(
  SELECT order_id AS OrderNumber, ordName, ordLastName, question, answer 
  FROM cart_survey 
  JOIN orders 
      ON cart_survey.order_id=orders.ordID 
  JOIN survey_answers 
      ON survey_answers.id=cart_survey.answer_id 
  JOIN survey_questions 
      ON survey_questions.id=cart_survey.question_id
) x
pivot
(
  min(answer)
  for question in ([Type of Surgery:], [Month of Surgery:], 
                [Year of surgery:], [Current Ostomy System Brand:], 
                [Degree of Satisfaction:])
) p
动态透视,获取运行时的列列表:

DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

select @cols = STUFF((SELECT distinct ', ' + QUOTENAME(question)
                    from survey_questions
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')


set @query 
      = 'SELECT OrderNumber, ordname, orderLastName,' + @cols + ' from 
         (
            SELECT order_id AS OrderNumber, ordName, ordLastName, question, answer 
            FROM cart_survey 
            JOIN orders 
                ON cart_survey.order_id=orders.ordID 
            JOIN survey_answers 
                ON survey_answers.id=cart_survey.answer_id 
            JOIN survey_questions 
                ON survey_questions.id=cart_survey.question_id
         ) x
         pivot 
         (
            min(answer)
            for question in (' + @cols + ')
         ) p '

execute(@query)

您需要执行透视/交叉选项卡查询。如果列是动态的,那么您需要动态SQL。好的,我必须研究一下,发现问题也不会改变。这也是我最喜欢的方法,但我实际上称之为可怜人的pivot!它实际上相当于SQLServerPivot子句。
DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

select @cols = STUFF((SELECT distinct ', ' + QUOTENAME(question)
                    from survey_questions
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')


set @query 
      = 'SELECT OrderNumber, ordname, orderLastName,' + @cols + ' from 
         (
            SELECT order_id AS OrderNumber, ordName, ordLastName, question, answer 
            FROM cart_survey 
            JOIN orders 
                ON cart_survey.order_id=orders.ordID 
            JOIN survey_answers 
                ON survey_answers.id=cart_survey.answer_id 
            JOIN survey_questions 
                ON survey_questions.id=cart_survey.question_id
         ) x
         pivot 
         (
            min(answer)
            for question in (' + @cols + ')
         ) p '

execute(@query)