SQL 过滤一组精确的值

问题描述 投票:0回答:1

我正在尝试查找具有一组精确匹配值的行。

例如,如果我正在查找 ID 0,1 和 2,我将使用值 ((7,2),(3,2),(7,1)) 查询类型、大小和名称日期。

ID     Type    Size   
----------------------
0      7      2       
1      3      2       
2      7      1       
3      7      6       
4      7      2       
5      7      null  

此查询的答案如下...(注意 ID 4 也会返回,因为它与 ID 0 具有相同的类型/大小)

ID     Type    Size    
---------------------
0      7      2       
1      3      2       
2      7      1       
4      7      2       

我尝试使用以下查询来执行此操作

SELECT * FROM my_table WHERE (Type,Size) IN ((7,2),(3,2),(7,1))

但是,如果其中一个值不存在,则这不起作用,例如

SELECT * FROM my_table WHERE (type,size) IN ((7,2),(3,2),(7,99))
应该返回 null,因为
(7,99)
不存在

如果包含空值也会中断

https://www.db-fiddle.com/f/2vxEEQNMhnK9oFGAhrQXip/2

sql postgresql relational-division
1个回答
0
投票

这是关系除法与余数问题的变体。

您正在尝试从表中获取与输入集(除数)匹配的行集(被除数),但可能有重复项,这会使事情变得复杂。

一种解决方案是将主表左连接到要查找的数据,然后通过检查

COUNT(*)
是否等于
COUNT(maintable.id)
来查找丢失的行,如果所有内容都匹配,就会这样做。我们需要将这个计数作为窗口函数来执行,因为我们希望最终结果包含所有行,而不仅仅是是/否答案。

我们可以使用

IS NOT DISTINCT FROM
来正确比较空值。

WITH ToFind(type, size) AS (
    VALUES
      (7::int,2::int),
      (3,2),
      (7,99)
),
Matches AS (
    SELECT
      mt.*,
      COUNT(*) OVER () - COUNT(mt.id) OVER () AS countMissing
    FROM ToFind tf
    LEFT JOIN my_table mt
      ON (tf.type, tf.size) IS NOT DISTINCT FROM (mt.type, mt.size)
)
SELECT
  m.id,
  m.type,
  m.size
FROM Matches m
WHERE m.countMissing = 0;

db<>小提琴

© www.soinside.com 2019 - 2024. All rights reserved.