2

SQL クエリで困っており、あなたの助けが必要です。簡単に言えば、選択したすべてのアイテムを含むパッケージを提供するすべてのホテルを返す必要があります

関連するテーブルは次のとおりです。

  • ホテル(hotel_id、hotel_name)
  • パッケージ(package_id、hotel_id、package_name)
  • アイテム(item_id、package_id、item_name)
  • package_items (package_id、item_id)

サンプルデータ

私の問題を説明するために、このサンプル データを見て、より明確に説明しましょう。

ホテル表

----------------------
ホテルID | ホテル名
----------------------
1 | ヒルトン
2 | ウェスティン
----------------------

パッケージ表

----------------------------------------------
package_id | ホテルID | パッケージ名
----------------------------------------------
1 | 1 | ゴールドパッケージ
2 | 1 | シルバーパッケージ
3 | 2 | スターパッケージ
4 | 2 | アルティメットパッケージ
----------------------------------------------

品目表

-------------------------------
item_id | 項目名
-------------------------------
1 | 部屋の無料アップグレード
2 | ディナー込み
3 | スパへのアクセス
4 | 無料の論文
-------------------------------

パッケージ品目表

----------------------
package_id | item_id
----------------------
1 | 2
1 | 3
1 | 4
2 | 2
2 | 3
3 | 4
4 | 1
4 | 2
4 | 3
4 | 4
----------------------

したがって、このデータを使用すると、たとえば、ヒルトンのゴールド パッケージにはディナー込み、スパへのアクセス、無料の書類が含まれていることがわかります。

ユーザーがこれらのさまざまなパッケージ アイテムをフィルター処理できるようにする機能をフロントエンドに構築しています。各項目に対するチェック ボックス。クリックすると結果がフィルタリングされ、ユーザーが選択したすべての項目を含むパッケージを提供するホテルのみが表示されます。

このためのSQLに少し困惑しています。これまでのところ、調査の結果、次のサンプル コードにたどり着きました (ここにあります: PostgreSQL where all in array )。

SELECT conversation_id FROM conversations_users

 WHERE user_id IN (1,2)

 GROUP BY conversation_id HAVING COUNT(*) = 2

このサンプル クエリでは、クエリの重要な部分は HAVING COUNT( ) = 2 セクションです。これにより、1 つだけではなく、選択されたすべてのアイテムが一致する必要があることをクエリに強制することが期待されます。これは、HAVING COUNT( ) = 2 セクションを使用しないクエリのデフォルトの動作です。

このアプローチと上記のテーブル構造を使用して、さまざまな JOIN クエリなどを含む、独自の要件に合わせてこのコードを調整しました。以下の例では、夕食付き、スパ アクセス、および無料の論文を選択しました。ヒルトンとウェスティンの両方がこれらのアイテムをすべて含むパッケージを提供しているため、ヒルトンとウェスティンの両方が戻ってくることを期待しています. ヒルトンの場合、ゴールド パッケージは私が選択したものを提供し、ウェスティンの場合、アルティメット パッケージは私が選択したものを提供します。

覚えておいてください、私は探しているすべてのアイテムを含むパッケージを提供するホテルを見つけようとしています.

ここに私がこれまでに持っているものがあります:

SELECT h.hotel_id, h.hotel_name FROM hotels h

  JOIN packages p       ON h.hotel_id   = p.hotel_id
  JOIN package_items pi ON p.package_id = pi.package_id
  JOIN items i          ON pi.item_id   = i.item_id

 WHERE i.item_id IN (2,3,4)

 GROUP BY h.hotel_id HAVING COUNT (*) = 3;

残念ながら、ここでは正確な結果が得られず、修正方法について困惑しています。私のためにこの問題を解決できる人への真剣な称賛.

4

2 に答える 2

3

最後のクエリを次のように更新します。

     SELECT h.hotel_id, h.hotel_name FROM hotels h
     JOIN packages p       ON h.hotel_id   = p.hotel_id
     JOIN package_items pi ON p.package_id = pi.package_id
     JOIN items i          ON pi.item_id   = i.item_id
     WHERE i.item_id IN (2,3,4)
     GROUP BY h.hotel_id 
     HAVING COUNT (DISTINCT i.item_id) = 3;

これにより、オファーに 3 つの異なるアイテムがあるホテルが返されます。

于 2012-11-10T14:56:19.330 に答える
1

package_name をグループ化に追加します... 次のように、最初の SELECT に入れて、何が機能しているかを示します

SELECT h.hotel_id, h.hotel_name, p.package_name FROM hotels h
  JOIN packages p       ON h.hotel_id   = p.hotel_id
  JOIN package_items pi ON p.package_id = pi.package_id
  JOIN items i          ON pi.item_id   = i.item_id
 WHERE i.item_id IN (2,3,4)
 GROUP BY h.hotel_name, p.package_name  HAVING COUNT(*) = 3;

+----------+------------+------------------+
| hotel_id | hotel_name | package_name     |
+----------+------------+------------------+
|        1 | Hilton     | Gold Package     |
|        2 | Weston     | Ultimate Package |
+----------+------------+------------------+
于 2012-11-10T16:20:13.430 に答える