簡體   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