3

一度に3つのテーブルからデータを取得しようとしています。テーブルは次のようになります。

カテゴリ

id
category
messageid

メッセージ

id
title
message

コメント

id
messageid
message

私が取得しようとしているのは、1つのメッセージ(WHEREidに基づく句があるため3)、3つのカテゴリ(メッセージにリンクされた3つのカテゴリがあるため)、および2つのコメント(メッセージにリンクされた2つのコメントがあるため)です。

次のクエリを使用してデータを取得しようとしています。

SELECT categories.category, messages.id, messages.title, messages.message, comments.count, comments.id as commentid, comments.message as commentmessage
FROM categories
RIGHT JOIN 
  (SELECT id, title, message
  FROM messages WHERE messaged.id = 3) messages
ON messages.id = categories.messageid
LEFT JOIN
  (SELECT count(id), id, message
  FROM comments
  GROUP BY id, message) comments
ON messages.id = comments.messageid
ORDER BY article.id DESC

ただし、このクエリを実行すると、6つの結果が得られます。

category      id  title      message      count  commentid  commentmessage
test          3   the title  the message  1      6          comment 1
test          3   the title  the message  1      5          comment 2
installation  3   the title  the message  1      6          comment 1
installation  3   the title  the message  1      5          comment 2
question      3   the title  the message  1      6          comment 1
question      3   the title  the message  1      5          comment 2

次のような結果を期待したところ:

category      id  title      message      count  commentid  commentmessage
test          3   the title  the message  1      6          comment 1
question      3   the title  the message  1      5          comment 2
installation  3   the title  the message  1      null       null

たった3行で、必要なすべてのデータを取得できるはずです。これも可能ですか?私はそれを完全に間違っていますか?

4

1 に答える 1

8

コメントで述べたように、ここにはいくつかの問題があります。

まず、3つのテーブルを結合しているので、得られる答えは正しいです。1 x 2x3行=6。

第二に、コメントの集計は実際には何も集計していません。結果からわかるように、2つのコメントに対して2になると思った場合、カウントは常に1です。IDでグループ化しているため、一意のIDごとにカウントが実行されます。これは常に1つです。おそらくmessageidでグループ化したいと思います

SELECT count(*), messageid
FROM comments
GROUP BY messageid

コメント自体を取得するには、別の結合または別のクエリを実行する必要があります。

また、コメントで説明されているように、通常、この方法で情報を取得することはありません。2つの関係は1対多であるため、通常は3つのクエリを実行するだけです。カテゴリが短い場合(およびSQL Serverを使用している場合)、カテゴリを独自の列(つまり、「テスト、インストール、質問」)に圧縮できます。これがあなたがそれをする方法です。

select id, title, message,
       (select CAST(category + ', ' as nvarchar(max))
        from @Categories c where messageid = m.id
        for xml path('')) as Categories
from @Messages m
where m.id = 3

実際、それを行うにはいくつかの方法がありますが、それは迅速で汚いです。その場合、コメントに対して1つの追加クエリのみが必要になります。前のクエリに参加して、次のように2行ですべての情報を取得できます。

select m.id, title, m.message,
       (select CAST(category + ', ' as nvarchar(max))
        from @Categories c where messageid = m.id
        for xml path('')) as Categories,
        cm.message
from @Messages m
left outer join @Comments cm on m.id = cm.messageid
where m.id = 3

ただし、情報の重複を避けるために、追加のクエリを作成することをお勧めします。

最後に、コメントカウントをどのように行うかを示したいと思います。

select m.id, title, m.message,
       (select CAST(category + ', ' as nvarchar(max))
        from @Categories c where messageid = m.id
        for xml path('')) as Categories,
        CommentCount,
        cm.message
from @Messages m
left outer join 
(   
    select messageid, COUNT(*) CommentCount
    from @Comments 
    group by messageid
) rsCommentCount on rsCommentCount.messageid = m.id

そして最後に、これがその動作を示すリンクです。

于 2012-07-25T21:36:54.633 に答える