我在数据库 A、B 和 C 中有 3 个表,它们共享同一列“名称”。 B 有一个属性“title”,C 有一个属性“age”。
我正在寻找一个 SQL 查询,我将不得不根据查询输入 B.title、C.age 或所有这些来选择 A 的所有内容。
到目前为止我尝试了什么,
SELECT * FROM A
LEFT JOIN B ON A.name = B.name
LEFT JOIN C ON A.name = C.name
WHERE B.title = COALESCE($1, B.title)
AND C.age = COALESCE($2, C.age)
$1 和 $2 来自外部程序。一些例子是 $1 = "Jones" 和 $2 = 12.
我从上述查询中得到一个空结果。 Left Join 似乎也很昂贵。有没有更快的方法可以在不加入表格的情况下实现这一目标。
如果 $1 为空,则查询将没有来自 B 表的任何连接。我想从 A 中取回名称。如果 $2 为空,则查询将不会加入 C 表,依此类推。如果两者都为空,它将返回 A 拥有的任何内容。
将
WHERE
子句的条件移动到各自的ON
子句中:
SELECT *
FROM A
LEFT JOIN B ON B.name = A.name AND B.title = $1
LEFT JOIN C ON C.name = A.name AND C.age = $2;
如果
$1
是null
,则条件:
B.title = $1
将返回
null
和完整的条件:
A.name = B.name AND B.title = $1
也将是
null
,这将导致 B
的所有行都不匹配。同样适用于
$2
.
如果给定名称不存在
B
,则条件B.title = COALESCE($1, B.title)
永远不会匹配,无论NULL
的值如何,它的计算结果都是$1
。 C
和 $2
相同。
如果参数是
NULL
,如果你想忽略条件,你应该写
SELECT * FROM A
WHERE ($1 IS NULL OR (SELECT title FROM B WHERE B.name = A.name) = $1)
AND ($2 IS NULL OR (SELECT age FROM C WHERE C.name = A.name) = $2)
你也可以试试
SELECT * FROM A
LEFT JOIN B USING (name)
LEFT JOIN C USING (name)
WHERE B.title IS NOT DISTINCT FROM COALESCE($1, B.title)
AND C.age IS NOT DISTINCT FROM COALESCE($2, C.age)
或(我更清楚地理解)
SELECT * FROM A
LEFT JOIN B USING (name)
LEFT JOIN C USING (name)
WHERE ($1 IS NULL OR $1 = B.title)
AND ($2 IS NULL OR $2 = C.age)
但是你应该检查那些查询计划,它们似乎更难优化。