3

製品IDのリストがあり、それらすべての製品が含まれている注文を確認したいと思います。Ordersテーブルは次のように構成されています。

order_id | product_id
----------------------
1        | 222
1        | 555
2        | 333

明らかに、PHPでいくつかのループを使用してそれを行うことができますが、純粋にmysqlでそれを行うためのエレガントな方法があるかどうか疑問に思いました。私の理想的なファンタジークエリは次のようになります。

SELECT order_id
FROM orders
WHERE (222,555) IN GROUP_CONCAT(product_id)
GROUP BY order_id

何か希望はありますか、それともトールキンを読みに行くべきですか?:)また、好奇心から、mysqlで不可能な場合、この機能を備えた他のデータベースはありますか?

4

4 に答える 4

4

あなたは近かった

SELECT order_id
FROM orders
WHERE product_id in (222,555) 
GROUP BY order_id
HAVING COUNT(DISTINCT product_id) = 2

関係代数での「好奇心から」の質問に関しては、これは除算で簡単に達成できます。AFAIK no RDBMSは、これをSQLで簡単にする拡張機能を実装していません。

于 2012-09-29T10:45:25.377 に答える
1

私は、having句でのみセット比較を行うことを好みます。

select order_id
from orders
group by order_id
having sum(case when product_id = 222 then 1 else 0 end) > 0 and
       sum(case when product_id = 555 then 1 else 0 end) > 0

これが言っていることは、注文に少なくとも1つの製品222と少なくとも1つの製品555があるすべての注文を取得することです。

私は2つの理由でこれを好みます。1つ目は一般化可能性です。222や555などのより複雑な条件を調整できます(「and」を「or」に変更するだけです)。または、333と555または555なしの222。

次に、クエリを作成するときに、条件を1つの場所(having句内)に配置するだけで済みます。

于 2012-09-29T14:26:39.287 に答える
1

データベースが適切に正規化されている、つまり特定の注文に重複する製品がないことを前提としています

Mysqlism:

select order_id
from orders
group by order_id
having sum(product_id in (222,555)) = 2

標準SQL:

select order_id
from orders
group by order_id
having sum(case when product_id in (222,555) then 1 end) = 2

重複している場合:

CREATE TABLE tbl
    (`order_id` int, `product_id` int)
;

INSERT INTO tbl
    (`order_id`, `product_id`)
VALUES
    (1, 222),
    (1, 555),
    (2, 333),
    (1, 555)
;

次にこれを行います:

select order_id
from tbl
group by order_id
having count(distinct case when product_id in (222,555) then product_id end) = 2

ライブテスト:http ://www.sqlfiddle.com/#!2 / fa1ad / 5

于 2012-09-29T14:42:36.350 に答える
1
CREATE TABLE orders
        ( order_id INTEGER NOT NULL
        , product_id INTEGER NOT NULL
        );
INSERT INTO orders(order_id,product_id) VALUES
 (1, 222 ) , (1, 555 ) , (2, 333 )
, (3, 222 ) , (3, 555 ) , (3, 333 ); -- order#3 has all the products

CREATE TABLE products AS (SELECT DISTINCT product_id FROM orders);

SELECT *
FROM orders o1
   --
   -- There should not exist a product
   -- that is not part of our order.
   --
WHERE NOT EXISTS (
        SELECT *
        FROM products pr
        WHERE 1=1
           -- extra clause: only want producs from a literal list
        AND pr.product_id IN (222,555,333)
           --  ... that is not part of our order...
        AND NOT EXISTS ( SELECT *
                FROM orders o2
                WHERE o2.product_id = pr.product_id
                AND o2.order_id = o1.order_id
                )
        );

結果:

 order_id | product_id 
----------+------------
        3 |        222
        3 |        555
        3 |        333
(3 rows)
于 2012-09-29T15:14:03.867 に答える