我尝试识别表格中的某些项目,这些项目在手动输入的文本中引用另一个表格中的项目标识符。数据结构设计不佳,并且没有什么东西可用于表之间的简单连接;他们不同步。
我有这个并且它有效,它不是很愉快:
SELECT i.id, (
SELECT c.text
FROM charges c
WHERE c.text LIKE CONCAT('%', i.order, '%')
AND c.state = 'paid'
) AS "charge text"
FROM items i
WHERE i.state = 'not paid'
AND (
SELECT c.text
FROM charges c
WHERE c.text LIKE CONCAT('%', i.order, '%')
AND c.state = 'paid'
) IS NOT NULL
ORDER BY id
charges
中的示例数据:
id state text
------------------------------------------
1 paid Lorem ipsum ABC123 sit amet
2 not paid DEF456 lorem ipsum sit amet
items
中的示例数据:
id state order
---------------------
1 not paid ABC123
2 not paid DEF456
目前,我需要子查询的第二个实例来删除因检查每个i.number
而选择了NULL原因的实例。我希望避免让子查询出现两次,但似乎不能使用common table expression {WITH
,如this answer中所示,因为它会在开始时定义,因此我无法将i.number
传递给它。我可能错了,因为我之前没有使用过CTE。
所以我想我有两个问题 - 首先,我可以定义子查询一次,然后只检查结果为NOT NULL;其次,我是否遇到了这个错误,并且有更好的方法来进行查询以避免检查的必要性?
答案 0 :(得分:2)
将此正确写为连接。当您不需要结果集中的子查询结果时,最好使用相关子查询。在这种情况下,您只需加入:
SELECT
i.id,
c.txt
FROM items i
INNER JOIN charges c ON
c.text like CONCAT('%', i.order , '%')
WHERE
c.state = 'paid'
AND i.state = 'unpaid'
您可以将AND c.txt IS NOT NULL
添加到该WHERE子句中,但是对于INNER JOIN,它可能不会捕获任何尚未被连接本身抑制的内容。
此外,由于您没有聚合或执行在主查询本身无法完成的任何其他逻辑,因此我取消了子查询。
答案 1 :(得分:0)
一般情况下,您可以使用LATERAL JOIN
:
SELECT i.id, sub."charge text"
FROM items i
LEFT JOIN LATERAL
(
SELECT c.text AS "charge text"
FROM charges c
WHERE c.text LIKE CONCAT('%', i.order, '%')
AND c.state = 'paid'
) sub ON true
WHERE i.state = 'not paid'
AND sub."charge text" IS NOT NULL
ORDER BY id;
SELECT i.id, sub."charge text"
FROM items i
JOIN LATERAL
(
SELECT c.text AS "charge text"
FROM charges c
WHERE c.text LIKE CONCAT('%', i.order, '%')
AND c.state = 'paid'
) sub ON true
WHERE i.state = 'not paid'
ORDER BY id;