用于选择与其他产品成分相同的产品的 SQL 查询

发布于 2024-08-04 08:27:56 字数 1154 浏览 2 评论 0原文

我有一个数据库,存储“市场上有售”的产品和“仍在开发中”的产品 位于两个单独的表中(market_productdev_product)。第三个表(物质)包含所有 产品可由哪些物质制成。其他两个表(marked_product_compdev_product_comp) 保持产品成分。

我想选择仍在开发中且由相同成分制成的产品 上市产品。

在以下(简化)示例中,查询必须从 dev_product 表中选择 ID = 2 的产品。

CREATE table market_product (ID SERIAL PRIMARY KEY);
CREATE table dev_product (ID SERIAL PRIMARY KEY);
CREATE table substance (ID SERIAL PRIMARY KEY);
CREATE table market_product_comp (prodID SERIAL, substID SERIAL, PRIMARY KEY(prodID,substID));
CREATE table dev_product_comp (devID SERIAL, substID SERIAL, PRIMARY KEY(devID,substID));

INSERT INTO market_product VALUES (1),(2);
INSERT INTO dev_product VALUES (1),(2);
INSERT INTO substance VALUES (1),(2),(3);
INSERT INTO market_product_comp VALUES (1,1),(1,2),(2,3);
INSERT INTO dev_product_comp VALUES (1,2),(2,1),(2,2);

如何编写这样的查询?


更新:

抱歉,我没有注意到我以含糊的方式提出了我的问题。

我想选择仍在开发中且与至少一种已上市产品具有相同成分的产品。例如,如果有一种由物质 {1,2} 制成的 dev_product 并且只有一种由物质 {1,2,3} 制成的 market_product,我想丢弃它dev_product,因为它具有不同的成分。我希望这能澄清。

I have a database that stores products "available on the market" and products "still in development"
in two separate tables (market_product and dev_product). A third table (substance) contains all
substances a product can made of. Other two tables (marked_product_comp and dev_product_comp)
mantains product compositions.

I want to select products still in development that are made of the same ingredients of
marketed products.

In the following (simplified) example the query must select product with ID = 2 from dev_product table.

CREATE table market_product (ID SERIAL PRIMARY KEY);
CREATE table dev_product (ID SERIAL PRIMARY KEY);
CREATE table substance (ID SERIAL PRIMARY KEY);
CREATE table market_product_comp (prodID SERIAL, substID SERIAL, PRIMARY KEY(prodID,substID));
CREATE table dev_product_comp (devID SERIAL, substID SERIAL, PRIMARY KEY(devID,substID));

INSERT INTO market_product VALUES (1),(2);
INSERT INTO dev_product VALUES (1),(2);
INSERT INTO substance VALUES (1),(2),(3);
INSERT INTO market_product_comp VALUES (1,1),(1,2),(2,3);
INSERT INTO dev_product_comp VALUES (1,2),(2,1),(2,2);

How to write such query?


UPDATE:

Sorry, I haven't noticed I asked my question in an ambiguous way.

I want to select products still in development that have the same composition of at least one marketed product. For example, if there is a dev_product made by substances {1,2} and only one market_product made by substances {1,2,3}, I want to discard that dev_product, because it has a different composition. I hope this clarify.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

海风掠过北极光 2024-08-11 08:27:56

下面的解决方案依赖于 COUNT() 忽略 NULL 的事实。

SELECT d1.devId, m1.prodId
FROM market_product_comp m1
CROSS JOIN dev_product_comp d1
LEFT OUTER JOIN dev_product_comp d2 
   ON (d2.substId = m1.substId AND d1.devId = d2.devId)
LEFT OUTER JOIN market_product_comp m2 
   ON (d1.substId = m2.substId AND m1.prodId = m2.prodId)
GROUP BY d1.devId, m1.prodId
HAVING COUNT(d1.substId) = COUNT(d2.substId)
   AND COUNT(m1.substId) = COUNT(m2.substId);

我在 MySQL 5.0.75 上对此进行了测试,但它都是 ANSI 标准 SQL,因此它应该适用于任何品牌的 SQL 数据库。

Here's a solution that relies on the fact that COUNT() ignores NULLs.

SELECT d1.devId, m1.prodId
FROM market_product_comp m1
CROSS JOIN dev_product_comp d1
LEFT OUTER JOIN dev_product_comp d2 
   ON (d2.substId = m1.substId AND d1.devId = d2.devId)
LEFT OUTER JOIN market_product_comp m2 
   ON (d1.substId = m2.substId AND m1.prodId = m2.prodId)
GROUP BY d1.devId, m1.prodId
HAVING COUNT(d1.substId) = COUNT(d2.substId)
   AND COUNT(m1.substId) = COUNT(m2.substId);

I tested this on MySQL 5.0.75, but it's all ANSI standard SQL so it should work on any brand of SQL database.

°如果伤别离去 2024-08-11 08:27:56

MySQL 中:

SELECT  *
FROM    dev_product dp
WHERE   EXISTS
        (
        SELECT  NULL
        FROM    market_product mp
        WHERE   NOT EXISTS
                (
                SELECT  NULL
                FROM    dev_product_comp dpc
                WHERE   dpc.prodID = dp.id
                        AND NOT EXISTS
                        (
                        SELECT  NULL
                        FROM    market_product_comp mpc
                        WHERE   mpc.prodID = mp.id
                                AND mpc.substID = dpc.substID
                        )
                )
                AND NOT EXISTS
                (
                SELECT  NULL
                FROM    market_product_comp mpc
                WHERE   mpc.prodID = mp.id
                        AND NOT EXISTS
                        (
                        SELECT  NULL
                        FROM    dev_product_comp dpc
                        WHERE   dpc.prodID = dp.id
                                AND dpc.substID = mpc.substID
                        )
                )

        )

PostgreSQL 中:

SELECT  *
FROM    dev_product dp
WHERE   EXISTS
        (
        SELECT  NULL
        FROM    market_product mp
        WHERE   NOT EXISTS
            (
            SELECT  NULL
            FROM    (
                SELECT  substID
                FROM    market_product_comp mpc
                WHERE   mpc.prodID = mp.ID
                ) m
            FULL OUTER JOIN
                (
                SELECT  substID
                FROM    dev_product_comp dpc
                WHERE   dpc.devID = dp.ID
                ) d
            ON  d.substID = m.substID
            WHERE   d.substID IS NULL OR m.substID IS NULL
            )
        )

这些查询都不使用 COUNT(*):只要找到一个不匹配的组件即可停止评估整个对。

请参阅我的博客中的这些条目以获取说明:

In MySQL:

SELECT  *
FROM    dev_product dp
WHERE   EXISTS
        (
        SELECT  NULL
        FROM    market_product mp
        WHERE   NOT EXISTS
                (
                SELECT  NULL
                FROM    dev_product_comp dpc
                WHERE   dpc.prodID = dp.id
                        AND NOT EXISTS
                        (
                        SELECT  NULL
                        FROM    market_product_comp mpc
                        WHERE   mpc.prodID = mp.id
                                AND mpc.substID = dpc.substID
                        )
                )
                AND NOT EXISTS
                (
                SELECT  NULL
                FROM    market_product_comp mpc
                WHERE   mpc.prodID = mp.id
                        AND NOT EXISTS
                        (
                        SELECT  NULL
                        FROM    dev_product_comp dpc
                        WHERE   dpc.prodID = dp.id
                                AND dpc.substID = mpc.substID
                        )
                )

        )

In PostgreSQL:

SELECT  *
FROM    dev_product dp
WHERE   EXISTS
        (
        SELECT  NULL
        FROM    market_product mp
        WHERE   NOT EXISTS
            (
            SELECT  NULL
            FROM    (
                SELECT  substID
                FROM    market_product_comp mpc
                WHERE   mpc.prodID = mp.ID
                ) m
            FULL OUTER JOIN
                (
                SELECT  substID
                FROM    dev_product_comp dpc
                WHERE   dpc.devID = dp.ID
                ) d
            ON  d.substID = m.substID
            WHERE   d.substID IS NULL OR m.substID IS NULL
            )
        )

Neither from these queries uses COUNT(*): it's enough to find but a single non-matching component to stop evaluating the whole pair.

See these entries in my blog for explanations:

无边思念无边月 2024-08-11 08:27:56
select d.* from dev_product d
 left join dev_product_comp dpc on d.Id = dpc.devId
where dpc.substID in 
  (select mpc.substID from market_product_comp  mpc 
    left join market_product mp on mp.Id = mpc.prodId)
select d.* from dev_product d
 left join dev_product_comp dpc on d.Id = dpc.devId
where dpc.substID in 
  (select mpc.substID from market_product_comp  mpc 
    left join market_product mp on mp.Id = mpc.prodId)
若言繁花未落 2024-08-11 08:27:56

仅选择所有产品物质均用于市场产品的开发产品 ID。

select 
   dp.id
from 
   dev_product dp
   inner join dev_product_comp dpc on dp.id = dpc.devid
where 
   dpc.substid in (select substid from market_product_comp) 
group by 
   dp.id
having 
   count() = (select count() from dev_product_comp where devid = dp.id)

不包括含有未在生产中使用的任何成分的产品。

Select only dev product ids where all the products substances are used in market products.

select 
   dp.id
from 
   dev_product dp
   inner join dev_product_comp dpc on dp.id = dpc.devid
where 
   dpc.substid in (select substid from market_product_comp) 
group by 
   dp.id
having 
   count() = (select count() from dev_product_comp where devid = dp.id)

Excludes products with ANY ingredients not used in production.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文