SQl中多使用EXISTS导致多查出了一条不符合条件的数据
原本的部分条件如下
and i.is_complement = '20'
and i.yxbz = '1'
AND (
i.name LIKE concat ('%', '红', '%')
OR EXISTS (
SELECT
*
FROM
commodity_suit_compose csc
WHERE
csc.suit_id = i.ID
AND csc.compose_name LIKE concat ('%', '红', '%')
)
)
查寻 i 表的name 和 csc 表中的compose_name,含有"红"这个字的数据,但是查出了一条compose_name不含红字且为空的数据
发现这条 compose_name
是 NULL!null明明不包含"红" 但是为什么null会被查出来呢,
原本我以为是 compose_name
为 NULL,有些数据库(尤其某些兼容性模式开启时)会 不严格排除 NULL 值条件失效的情况,导致 EXISTS
子查询仍返回了记录 → 主记录被错误保留。
但后面我加了 is not null的条件还是能查出来,但是大概能猜到问题出在EXISTS里面
,最后发现是聚合子查询和EXISTS里面的查询过滤不一致导致的,
我的聚合子查询是这样写的
(
SELECT
string_agg ( compose_name, ',' )
FROM
(
SELECT
compose_name
FROM
commodity_suit_compose csc
WHERE
csc.suit_id = i.ID
AND csc.merchant_id = i.merchant_id
AND csc.yxbz = '1'
AND csc.strike_out = '0'
ORDER BY
csc.num DESC
) AS sorted_names
) "compose_name"
EXISTS是这样写的
EXISTS (
SELECT
*
FROM
commodity_suit_compose csc
WHERE
csc.suit_id = i.ID
AND csc.compose_name LIKE concat ( '%', '红', '%' )
)
-
聚合(string_agg) 和 判断存在(EXISTS) 必须在同一个“数据子集”上做过滤,才能保证逻辑一致。
-
在聚合时只看了“同商家、上架、未删除”的行,却在
EXISTS
里忘了这几条,导致EXISTS
能拿到一些“被聚合丢掉”的行。 -
最后给EXISTS加上相同的过滤条件即可
-
EXISTS (
SELECT
*
FROM
commodity_suit_compose csc
WHERE
csc.suit_id = i.ID
AND csc.merchant_id = i.merchant_id
AND csc.yxbz = '1'
AND csc.strike_out = '0'
AND csc.compose_name LIKE concat ( '%', '红', '%' )
)