繁体   English   中英

选择至少与列表中的所有项目匹配的记录

[英]Select records that match at least all items in a list

假设我有以下数据库表:

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   |

我的问题是:什么是查询第一个表并获取至少具有上一个查询中返回的所有类型的所有记录的最佳方法?

在上面的示例中,名称“ Third”的类型为ABC。使用这些作为列表,我只想检索“ First”记录(因为“ First”具有ABCD)而不是“ Second”(因为“ Second”具有只有AB-缺少C)。

IN语句匹配eveything,并且我希望查询至少匹配“类型”列表中的所有项目。 该列表不一定来自sql语句,但可以提供

编辑:我正在使用MySQL

询问

包括两个数据库的同一查询的两个变体。


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"
)
  • 按名称分组类型
  • 利用Array @>contains operator )与查询进行比较

设定

(适用于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)
;

在标准SQL中,你可以做到这一点的join ,并group by与一些过滤。 以下假设type s对于每个表中的每个名称都是唯一的:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM