一个示例涉及在SQL中操纵select语句

时间:2018-11-16 23:01:35

标签: sql database oracle

(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

3 个答案:

答案 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
                  );