【问题标题】:Poor Man's SQL Pivot. List Questions as Columns and Answers per User in one row穷人的 SQL 枢轴。将问题列为列并在一行中列出每个用户的答案
【发布时间】:2013-12-19 23:52:25
【问题描述】:

当前查询

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

结果

OrderNumber ordName ordLastName 问题答案 8591 Larry Marshburn 手术类型:结肠造口术 8591 Larry Marshburn 手术月:2 8591 Larry Marshburn 手术年份:2010 8591 Larry Marshburn 当前造口系统品牌:ConvaTec 8591 Larry Marshburn 满意程度:有点满意 8593 Melvin Belcher 手术类型:泌尿造口术 8593 Melvin Belcher 手术月:9 8593 Melvin Belcher 手术年份:2010 8593 Melvin Belcher 当前造口系统品牌:ConvaTec 8593 Melvin Belcher 满意程度:非常满意

如何正确查询表以提取如下所示的结果? 姓名和姓氏在一行,列的问题和每列的答案。

期望的结果

OrderNumber ordName ordLastName “手术类型” “手术月份” “手术年份”等。 8591 拉里·马什伯恩结肠造口术 2 2010 8593 Melvin Belcher 泌尿造口术 9 2010

【问题讨论】:

  • 您需要进行Pivot/cross tab 查询。如果列是动态的,则需要动态 SQL。

标签: tsql


【解决方案1】:

发布的答案有效,但笨拙且缓慢。你可以做我所说的并行聚合:

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

这将在桌子上进行一次而不是三次,并且非常短。这不是一个完整的演练,但您肯定可以根据自己的需要调整这个概念。

【讨论】:

  • 也是我最喜欢的方法,但我实际上称之为“穷人的支点”
  • 实际上相当于SQL Server PIVOT子句。
【解决方案2】:

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

【讨论】:

  • 好的,我必须调查一下,发现问题也没有改变。
【解决方案3】:

这被称为PIVOT,有两种方法可以使用静态版本或动态版本执行此操作。

静态版本是当您将值硬编码为列时:

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)

【讨论】:

    【解决方案4】:

    这是 MySQL 版本

    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
    

    【讨论】:

      【解决方案5】:

      这是 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]
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-12-23
        • 1970-01-01
        • 2012-09-23
        • 2018-04-11
        • 2023-03-20
        • 2020-02-14
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多