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>それぞれに対して同じ数または行が返されることが保証されているため、結果セット行ごとに 'sを安全に配置できます。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 に答える