1

我有一个表,想将其行转换为列,类似于数据透视表,但不进行汇总。

例如,我有以下表格:

Question
--QuestionID
--QuestionText

Response
--ResponseID
--ResponseText
--QuestionID

基本上我希望能够创建一个动态表,例如:

Question 1 Text | Question 2 Text | Question 3 Text
---------------------------------------------------
Response 1.1 Text | Response Text 1.2 | Response 1.3
Response 2.1 Text | Response Text 2.2 | Response 2.3
Response 3.1 Text | Response Text 3.2 | Response 3.3
Response 4.1 Text | Response Text 4.2 | Response 4.3

主要要求是我在设计时不知道问题文本是什么。

请有人帮忙 - 我正在拔头发:oS

从本质上讲,您可以保证在这种情况下每个相应的问题都会得到响应。

4

2 回答 2

7

SQL除非您知道设计时的列数(即问题),否则您不能这样做(动态查询除外)。

您应该以表格格式提取所需的数据,然后在客户端进行处理:

SELECT  *
FROM    Question
LEFT OUTER JOIN
        Response
ON      Response.QuestionId = Question.QuestionID

或者,可能是这个(在SQL Server 2005+Oracle 8i+PostgreSQL 8.4+):

SELECT  *
FROM    (
        SELECT  q.*, ROW_NUMBER() OVER (ORDER BY questionID) AS rn
        FROM    Question q
        ) q
LEFT OUTER JOIN
        (
        SELECT  r.*, ROW_NUMBER() OVER (PARTITION BY questionID ORDER BY ResponseID) AS rn
        FROM    Response r
        ) r
ON      r.QuestionId = q.QuestionID
        AND q.rn = r.rn
ORDER BY
        q.rn, q.QuestionID

后一个查询将以这种形式为您提供结果(如果您有4问题):

rn      question      response
---          ---           ---
1     Question 1  Response 1.1
1     Question 2  Response 2.1
1     Question 3  Response 3.1
1     Question 4  Response 4.1
2     Question 1  Response 1.2
2     Question 2  Response 2.2
2     Question 3  NULL
2     Question 4  Response 4.2
3     Question 1  NULL
3     Question 2  NULL
3     Question 3  Response 3.3
3     Question 4  NULL

,这是它将以表格形式输出数据,并rn标记行号。

每次您rn在客户端上看到更改时,您只需关闭<tr>并打开新的。

您可以安全地<td>为每个结果集行放置一个,因为保证为每个结果集返回相同的数量或行rn

这是一个相当常见的问题。

SQL只是不是返回具有动态列数的数据的正确工具。

SQL对集合进行操作,列布局是集合的隐含属性。

您应该在设计时定义您想要获得的集合的布局,就像您在 中定义变量的数据类型一样C

C适用于严格定义的变量,SQL适用于严格定义的集合。

请注意,我并不是说这是最好的方法。这只是工作方式SQL

更新:

SQL Server中,您可以直接将表格HTML从数据库中拉出:

WITH    a AS
        (
        SELECT  a.*, ROW_NUMBER() OVER (PARTITION BY question_id ORDER BY id) AS rn
        FROM    answer a
        ),
        rows AS (
        SELECT  ROW_NUMBER() OVER (ORDER BY id) AS rn
        FROM    answer a
        WHERE   question_id =
                (
                SELECT  TOP 1 question_id
                FROM    answer a
                GROUP BY
                        question_id
                ORDER BY
                        COUNT(*) DESC
                )
        )
SELECT  (
        SELECT  COALESCE(a.value, '')
        FROM   question q
        LEFT JOIN
                a
        ON      a.rn = rows.rn
                AND a.question_id = q.id
        FOR XML PATH ('td'), TYPE
        ) AS tr
FROM    rows
FOR XML PATH(''), ROOT('table')

有关更多详细信息,请参阅我的博客中的此条目:

于 2009-07-27T10:32:40.580 回答
0

首先进行分组和聚合,使用 Quassnoi 的答案作为中间结果。

只有当您不再对结果进行面向集合的操作时,才应进行交叉制表。一些 SQL 方言使用 PIVOT、TRANSFORM 或 CROSSTABULATE 等关键字来完成此操作,但使用 XSLT 可能会更好。

于 2009-07-27T12:30:21.383 回答