Выберите записи, которые соответствуют по крайней мере всем элементам в списке

0

Предполагая, что у меня есть следующая таблица базы данных:

ID | Name    | Type     | Value|
--- --------- ---------- ------
1  | First   | A        | 10   |
2  | First   | B        | 20   |
3  | First   | C        | 30   |
4  | First   | D        | 40   |
5  | Second  | A        | 10   |
6  | Second  | B        | 20   |

и возвращается предыдущий запрос:

ID | Name    | Type     | Value|
--- --------- ---------- ------
1  | Third   | A        | 10   |
2  | Third   | B        | 20   |
3  | Third   | C        | 30   |

Мой вопрос: каков наилучший способ запросить первую таблицу и получить все записи, имеющие хотя бы весь тип, возвращаемый в предыдущем запросе?

В приведенном выше примере имя "Третий" имеет типы AB C. Используя их как список, я хотел бы получить только "первые" записи (так как "First" имеет ABCD), но не "Second" (так как "Second" имеет только AB - отсутствует C).

Оператор IN соответствует eveything, и я хочу, чтобы запрос соответствовал по крайней мере всем элементам в моем "типе" списке. Список не обязательно поступает из SQL-запроса, но может быть предоставлен

EDIT: Я работаю с MySQL

  • 1
    Продолжать. Попробуй что-нибудь.
  • 0
    Я удалил несовместимые теги базы данных. Пожалуйста, пометьте только ту базу данных, которую вы действительно используете.
Теги:

2 ответа

0
Лучший ответ

запрос

Включены два варианта одного и того же запроса для любой базы данных.


MySQL

DBFiddle

SELECT main.* 
FROM   main
LEFT JOIN (
  SELECT name, json_arrayagg(type) as type
  FROM main
  GROUP BY name
) AS main_agg USING(name)

WHERE EXISTS (
  SELECT 1
  FROM (
    select json_arrayagg(type) as type
    from query 
    group by name
  ) AS query_agg
  WHERE JSON_CONTAINS(main_agg.type, query_agg.type)
)
  • типы групп по названию
  • использует функцию JSON_CONTAINS для сравнения таблицы с запросом

Postgres

SQLFiddle

WITH main_agg AS
(
  SELECT name, array_agg(type) "type"
  FROM main
  GROUP BY name
)

SELECT main.* 
FROM   main
JOIN   main_agg USING(name)
WHERE EXISTS (
  SELECT 1
  FROM (select array_agg(type) "type" from query group by name) query_agg
  WHERE main_agg."type" @> query_agg."type"
)

Настроить

(Работает для MySQL или PostgreSQL)

CREATE TABLE main
    (ID int, Name varchar(6), Type varchar(1), Value int)
;

INSERT INTO main
    (ID, Name, Type, Value)
VALUES
    (1, 'First', 'A', 10),
    (2, 'First', 'B', 20),
    (3, 'First', 'C', 30),
    (4, 'First', 'D', 40),
    (5, 'Second', 'A', 10),
    (6, 'Second', 'B', 20)
;


CREATE TABLE query
    (ID int, Name varchar(5), Type varchar(1), Value int)
;

INSERT INTO query
    (ID, Name, Type, Value)
VALUES
    (1, 'Third', 'A', 10),
    (2, 'Third', 'B', 20),
    (3, 'Third', 'C', 30)
;
  • 0
    Здравствуйте и спасибо, я работаю с MySQL. Кажется, что он не поддерживает WITH и EXISTS, я получаю некоторые ошибки. Как это можно написать в MySQL?
  • 0
    EXISTS должен работать в MySQL, а запросы WITH могут быть просто выполнены подзапросами.
Показать ещё 5 комментариев
0

В стандартном SQL вы можете сделать это как join и group by помощью некоторой фильтрации. Далее предполагается, что type уникален для каждого имени в каждой таблице:

with prevq as (
      . . .
     )
select t.name
from t join
     prevq
     on t.type = prevq.type
group by t.name
having count(*) = (select count(*) from prevq);

РЕДАКТИРОВАТЬ:

MySQL не поддерживает CTE (до 8.0). Это достаточно легко обойти:

select t.name
from t join
     (<your query here>) prevq
     on t.type = prevq.type
group by t.name
having count(*) = (select count(*) from (<your query here>) prevq);
  • 0
    Привет и спасибо, пожалуйста, смотрите мой комментарий в другом посте.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню