Одним из примеров является манипулирование оператором выбора в SQL - PullRequest
0 голосов
/ 17 ноября 2018

(вопрос новичка в SQL). Я работаю над запросом, который может найти всех рабочих, которые создают продукты, которые включают все продукты, созданные Worker с 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 голосов
/ 17 ноября 2018

Это:

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', только если их число равно количеству продуктов, которые произвел работник с идентификатором '18' .

0 голосов
/ 17 ноября 2018

Вероятно, самый простой метод использует 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
                  );
0 голосов
/ 17 ноября 2018

Для начала вам нужен список всех продуктов, созданных работником. 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

Теперь вы должны выяснить, есть ли у каждого продукта каждый продукт, поэтому вы проверяете с помощью таблицы Creates

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) не считает нули

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...