2

私は金曜日のケースを持っている必要があります...次のテーブルとデータがあるとします。

+------------+
| Park       |
+------------+
| Cape Cod   |
| Blue Ridge |
| Ice Age    |
+------------+

+--------+
| Tag    |
+--------+
| Biking |
| Skiing |
+--------+

+---------------------+
| ParkTags            |
+------------+--------+
| Cape Cod   | Biking |
| Blue Ridge | Hiking |
| Ice Age    | Biking |
| Ice Age    | Hiking |
+------------+--------+

つまり、公園は1つのテーブルに格納され、もう1つのテーブルにはタグが格納され、3番目のテーブルは1つ以上のタグを公園にリンクします。

私がやろうとしているのは、1つ以上のタグを選択し、すべてのタグを持つすべての公園を返すことです。上記の情報から、タグは次のように公園に関連付けられています。

サイクリング:ケープコッド氷河期

ハイキング:ブルーリッジアイスエイジ

サイクリングとハイキング:氷河期

私の質問は、クエリで何が間違っているのかということです。私が取得しようとしているのは、BikingANDHikingというタグが付いているすべての公園です。

# My query so far

SELECT
    Park.name as Park,
    Tag.name as Tag

FROM
    ParkTags
    JOIN Park ON Park.id = ParkTags.fk_park_id
    JOIN Tag  ON Tag.id  = ParkTags.fk_tag_id

WHERE
    Tag.name = 'Biking' AND Tag.name = 'Hiking'

ORDER BY
     Park.name

私の期待する出力は、アイスエイジパークのみを取得することです。そのクエリを実行すると、結果はゼロになります。条件でORのANDを変更すると、3つのパークすべてになります。

ありがとう。

4

5 に答える 5

2

Tag.nameは、値「Biking」と「Hiking」を同時に持つことはできません。

于 2012-04-27T22:19:31.217 に答える
2

さて、私が最初に目にする問題は、ALLタグを持つすべての公園を返したいということですが、where句を使用して、返すタグを指定しています...上記の誰かが言ったように、あなたは行は両方の基準に同時に一致しますが(AND演算子)、タグ列のwhere句はいずれにせよ要件を満たしていないので、それは重要ではないと思います。

これがテーブルの定義です

parks
---------
id
name

tag
------
id
name

parktags
-------
id
fk_parks_id
fk_tags_id

私はおそらく、parktagsテーブルの左結合から始めます。

SELECT p.name, t.name 
FROM   parktags PT
          LEFT JOIN parks P ON p.id = pt.fk_parks_id
          LEFT JOIN tag T ON t.id = pt.fk_tags_id

これにより、すべてのパークタグが、一致するパークとタグとともに提供されます。ここで、パークタグに複数のエントリがあるものだけを返す必要があります。このようなことを試してみましょう

SELECT p.name, t.name 
FROM   parktags PT
          LEFT JOIN parks P ON p.id = pt.fk_parks_id
          LEFT JOIN tag T ON t.id = pt.fk_tags_id
GROUP BY pt.fk_parks_id
HAVING COUNT(pt.fk_tags_id) > 1

HAVINGはWHEREと同じように機能しますが、HAVINGでは条件チェックに集計を使用できますが、WHEREでは使用できません。where句で副選択を使用することもできますが、特に問題はありませんが、副選択には独自の個別の実行プランが必要であり、結合よりもコストがかかります。

目の前にコンソールがないので、テストできません。何か問題があると思います。正しくするために、HAVING句とGROUP BY句をもう少し試してみる必要があるかもしれませんが、それはそれらの線に沿ったものになります。どうなるか教えてください...

于 2012-04-28T03:09:36.507 に答える
1
SELECT p.name, 
       group_concat(t.name)

FROM Park p
JOIN ParkTags pt ON pt.fk_park_id = p.id
JOIN Tag t       ON pt.fk_tag_id  = t.id

WHERE (
    SELECT COUNT(*) 

    FROM ParkTags pt 
    JOIN Tag t ON t.id = pt.fk_tag_id 

    WHERE t.name in ('Biking','Hiking') 
    AND pt.fk_park_id=p.id
) = 2

GROUP BY p.id
于 2012-04-27T22:29:50.127 に答える
1

Nesimの答えを少し変更してみることもできます。

SELECT p.name, GROUP_CONCAT(t.name) AS Name list
FROM Park p
        INNER JOIN ParkTags pt ON pt.fk_park_id = p.id
        INNER JOIN Tag t ON t.id = pt.fk_tag_id
WHERE   t.name in ('Biking','Hiking')
GROUP BY p.name
HAVING COUNT(DISTINCT t.id) = 2
于 2012-04-28T00:16:22.963 に答える
0
SELECT
    Parks.Name
FROM
    Park 
WHERE 
    EXISTS (SELECT * FROM ParkTags b WHERE b.Tag = 'Hiking' AND b.Name = Park.Name)
    AND EXISTS (SELECT * FROM ParkTags c WHERE c.Tag = 'Biking' AND c.Name = Park.Name)

そんな感じ?一致するタグの存在を確認しています。これは適切にスケーリングされません。

于 2012-04-27T22:27:27.313 に答える