我有一个存储“市场上可用”产品的数据库和“仍处于开发阶段”的产品
在两个单独的表中(market_product
和dev_product
)。第三个表(实质)包含所有
产品可以制成的物质。其他两个表格(marked_product_comp
和dev_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
,因为它有不同的成分。我希望这澄清一下。
答案 0 :(得分:1)
这是一个依赖于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数据库。
答案 1 :(得分:0)
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)
答案 2 :(得分:0)
仅选择开发产品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)
不包括生产中未使用的任何成分的产品。
答案 3 :(得分:0)
在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(*)
:它足以找到一个不匹配的组件来停止评估整个对。
请参阅我的博客中的这些条目以获取解释:
PostgreSQL
,FULL OUTER JOIN
)MySQL
,EXISTS
)