MySQL – 选择value = X的行,或者如果没有匹配,则选择value = null

如何在表中找到val_b具有特定值的所有行,但如果不存在这样的行,我想看看是否存在匹配特异性较低的行,因此val_b为null.

从下表中,我想选择val_a = X和val_b = T的位置,并获取ID为1的行.

如果我选择val_a = X和val_b = V的位置并获取ID为3且ID为4的行.由于第1行和第2行不匹配,我将解决具有较低特异性但仍匹配val_a的行.

| ID | val_a | val_b |
| -- | ----- | ----- |
| 1  | X     | T     |
| 2  | X     | U     |
| 3  | X     | null  |
| 4  | X     | null  |
| 5  | Y     | null  |

这可以直接在数据库查询中执行吗?类似于语法左关联的XOR运算符…

最佳答案 试试这个查询:

SELECT ID, val_a, val_b
FROM yourTable
WHERE
    val_a = 'X' AND (val_b = 'V' OR
                     (NOT EXISTS (SELECT 1 FROM yourTable
                              WHERE val_a = 'X' AND val_b = 'V') AND val_b IS NULL));

《MySQL – 选择value = X的行,或者如果没有匹配,则选择value = null》

Demo

这里的逻辑是,如果满足下列条件之一,我们将保留记录:

> val_b匹配预期的(非NULL)值,或
> val_b为NULL,并且没有匹配的非NULL val_b记录

EXISTS子句涵盖了第二种情况,它断言没有匹配的非NULL val_b记录.

当搜索val_a =’X’和val_b =’T’时,仅使用上述查询返回ID:1记录.

如果您使用的是MySQL 8,那么我们可以在这里使用分析函数:

WITH cte AS (
    SELECT ID, val_a, val_b,
        COUNT(CASE WHEN val_a = 'X' AND val_b = 'V' THEN 1 END)
            OVER () cnt
    FROM yourTable
)

SELECT ID, val_a, val_b
FROM cte
WHERE val_a = 'X' AND (val_b = 'V' OR (val_b IS NULL AND cnt = 0));

Demo

但请注意,即使在这种情况下,我们仍然需要使用子查询.

点赞