5

私は3つのテーブルを持っていますtag, page,pagetag

以下のデータで

ページ

ID      NAME
1       page 1
2       page 2
3       page 3
4       page 4

鬼ごっこ

ID      NAME
1       tag 1
2       tag 2
3       tag 3
4       tag 4

ページタグ

ID   PAGEID  TAGID
1    2        1
2    2        3
3    3        4
4    1        1
5    1        2
6    1        3

単一のクエリで SQL を使用して、各ページの対応するタグ名を含む文字列を取得したいと考えています。これは私の望ましい出力です。

ID      NAME       TAGS
1       page 1     tag 1, tag 2, tag 3
2       page 2     tag 1, tag 3
3       page 3     tag 4
4       page 4    

これはSQLで可能ですか?


私はMySQLを使用しています。それにもかかわらず、可能であれば、データベース ベンダーに依存しないソリューションが必要です。

4

6 に答える 6

3

はい、以下のように 3 つの方法で実行できます。

SELECT page_tag.id, page.name, group_concat(tags.name)
FROM tag, page, page_tag
WHERE page_tag.page_id = page.page_id AND page_tag.tag_id = tag.id;

テストされておらず、おそらくもう少し効率的に記述できる可能性がありますが、開始する必要があります!

また、MySQL が想定されているため、MSSQL ではうまく機能しない可能性があります。また、MySQL はフィールド名のハイフンに無頓着なので、上記の例ではアンダースコアに変更されています。

于 2008-09-01T10:23:06.563 に答える
3

セルジオ・デル・アモ:

ただし、タグのないページは取得できません。左外部結合を使用してクエリを作成する必要があると思います。

SELECT pagetag.id, page.name, group_concat(tag.name)
FROM
(
    page LEFT JOIN pagetag ON page.id = pagetag.pageid
)
LEFT JOIN tag ON pagetag.tagid = tag.id
GROUP BY page.id;

あまりきれいなクエリではありませんが、必要なものが得られるはずです-pagetag.id上記の例では4ページ目group_concat(tag.name)になりnullますが、ページは結果に表示されます。

于 2008-09-01T11:17:34.483 に答える
1

私は結合で遊ぶ解決策を得ました。クエリは次のとおりです。

SELECT
    page.id AS id,
    page.name AS name,
    tagstable.tags AS tags
FROM page 
LEFT OUTER JOIN 
(
    SELECT pagetag.pageid, GROUP_CONCAT(distinct tag.name) AS tags
    FROM tag INNER JOIN pagetag ON tagid = tag.id
    GROUP BY pagetag.pageid
)
AS tagstable ON tagstable.pageid = page.id
GROUP BY page.id

そして、これは出力になります:

id   name    tags
---------------------------
1    page 1  tag2,tag3,tag1
2    page 2  tag1,tag3
3    page 3  tag4
4    page 4  NULL

別の方法でクエリの速度を上げることはできますか?

于 2008-09-01T11:34:36.110 に答える
1

私の知る限り、SQL92 では文字列の連結方法が定義されていません。つまり、ほとんどのエンジンには独自のメソッドがあります。

データベースに依存しない方法が必要な場合は、データベースの外部で行う必要があります。

(Oracle以外ではテストされていません)

オラクル

SELECT field1 | ', ' | field2
FROM table;

MSSQL

SELECT field1 + ', ' + field2
FROM table;

MySQL

SELECT concat(field1,', ',field2)
FROM table;

PostgeSQL

SELECT field1 || ', ' || field2
FROM table;
于 2008-09-01T10:50:28.790 に答える
0

上記の例では、ページ 4 の pagetag.id と group_concat(tag.name) は null になりますが、ページは結果に表示されます。

COALESCE次のことが必要な場合は、関数を使用して Null を削除できます。

select COALESCE(pagetag.id, '') AS id ...

パラメータのリストから最初の null 以外の値を返します。

于 2008-09-01T11:37:58.787 に答える
0

複数の更新プログラムを使用する必要があるかもしれないと思います。

次のようなもの(テストされていません):

select ID as 'PageId', Name as 'PageName', null as 'Tags'
into #temp 
from [PageTable]

declare @lastOp int
set @lastOp = 1

while @lastOp > 0
begin
    update p
    set p.tags = isnull(tags + ', ', '' ) + t.[Tagid]
    from #temp p
        inner join [TagTable] t
            on p.[PageId] = t.[PageId]
    where p.tags not like '%' + t.[Tagid] + '%'

    set  @lastOp == @@rowcount
end

select * from #temp

醜いけど。

その例は T-SQL ですが、MySql には使用されているすべてのものと同等のものがあると思います。

于 2008-09-01T10:33:16.553 に答える