(SQL菜鸟问题)我正在研究一个查询,该查询可以找到所有创建产品的工作人员,其中包括ID = 18的所有工作人员创建的产品。
CREATE TABLE Creates(
ID CHAR(10),
PRODUCTID CHAR(10),
PRIMARY KEY (ID, PRODUCTID),
FOREIGN KEY(ID) REFERENCES Worker(ID) ON DELETE CASCADE,
};
CREATE TABLE Worker(
ID CHAR(10) PRIMARY KEY,
};
这是我表中的内容现在创建:
INSERT INTO Creates VALUES('2', 'S100');
INSERT INTO Creates VALUES('2', 'D111');
INSERT INTO Creates VALUES('4', 'D111');
INSERT INTO Creates VALUES('4', 'S119');
INSERT INTO Creates VALUES('6', 'S2');
INSERT INTO Creates VALUES('6', 'D231');
INSERT INTO Creates VALUES('8', 'S103');
INSERT INTO Creates VALUES('10', 'S109');
INSERT INTO Creates VALUES('12', 'S189');
INSERT INTO Creates VALUES('14', 'S982');
INSERT INTO Creates VALUES('20', 'E341');
INSERT INTO Creates VALUES('22', 'E100');
INSERT INTO Creates VALUES('18', 'D111');
INSERT INTO Creates VALUES('18', 'D231');
INSERT INTO Creates VALUES('2', 'D231');
INSERT INTO Creates VALUES('24', 'D111');
INSERT INTO Creates VALUES('24', 'D231');
我们看到,实际上正确的输出应该是ID 2和24。
这是我现在要实现的,但我认为这不正确,所以我想听听任何人或任何可以帮助我解决问题的建议,谢谢。
SELECT DISTINCT ID
FROM Creates
WHERE PRODUCTID = ALL (SELECT PRODUCTID FROM Creates WHERE ID = '18')
ORDER BY ID ASC
;
答案 0 :(得分:1)
此:
SELECT ID
FROM
(SELECT *
FROM Creates
WHERE PRODUCTID IN (SELECT PRODUCTID FROM Creates WHERE ID = '18')
AND (ID <> '18')
) AS t
GROUP BY ID
HAVING COUNT(*) = (SELECT COUNT(*) FROM Creates WHERE ID = '18')
返回
2
24
如您所见,Worker
表根本没有涉及。
仅当生产编号为Creates
的工人的产品的工人的编号等于编号为{的工人的产品的编号时,才从'18'
表中检索结果。 {1}}已产生。
答案 1 :(得分:0)
首先,您需要由工作人员18创建的所有产品的列表
SELECT product_id FROM Creates WHERE ID = '18'
然后您需要所有员工的列表
SELECT ID as worker_id FROM Workers WHERE ID <> '18'
现在您要创建两个结果的笛卡尔积,以列出所有可能的组合
WITH products as (
SELECT product_id FROM Creates WHERE ID = '18'
), employees as (
SELECT ID as worker_id FROM Workers WHERE ID <> '18'
)
SELECT product_id, worker_id
FROM products
CROSS JOIN employees
现在,您必须查找员工是否拥有所有产品,然后使用创建表进行检查
WITH products as (
SELECT product_id FROM Creates WHERE ID = '18'
), employees as (
SELECT ID as worker_id FROM Workers WHERE ID <> '18'
), allMatches as (
SELECT product_id, worker_id
FROM products
CROSS JOIN employees
)
SELECT A.worker_id
FROM allMatches A
LEFT JOIN Creates C
ON A.product_id = C.product_id
AND A.worker_id = C.worker_id
GROUP BY A.worker_id
HAVING COUNT(*) = COUNT(C.product_id)
如果工作人员未创建产品,则LEFT JOIN
将在比赛中创建NULL。而且COUNT(C.product_id)
不会计算空值
答案 2 :(得分:0)
可能最简单的方法是使用listagg()
:
select c.id,
listagg(c.productid, ',') within group (order by c.productid) as products
from creates c join
creates c18
on c18.productid = c.productid and
c18.id = 18 and
c.id <> 18
group by c.id
having products = (select listagg(c.productid, ',') within group (order by c.productid) as products
from creates c
where c.id = 18
);