背景:文档管理系统中有两种不同的文档类型。Doc Type A 和 Doc Type B 都有一个 Ticket # 和一个 Ticket Date。我们正在寻找:Doc Type A 文档没有匹配的 Doc Type B 文档(不存在)且 Ticket # 和 Ticket Date 相同。类似的 Doc Type B 文档具有相同的 Ticket # 但不同的 Ticket Date。我们想忽略这些。看起来很简单......但我被卡住了。到目前为止,我所拥有的是这样的:
SELECT
DISTINCT ki110.keyvaluechar AS "Ticket #",
ki101.keyvaluedate AS "Ticket Date"
FROM
itemdata
LEFT OUTER JOIN
hsi.keyitem110 ki110 on ( itemdata.itemnum = ki110.itemnum )
LEFT OUTER JOIN
hsi.keyitem101 ki101 on ( itemdata.itemnum = ki101.itemnum )
WHERE
ki101.keyvaluedate BETWEEN '01-01-2021' AND '01-31-2021'
AND
(
itemdata.itemtypenum = 178
) -- this is Doc Type A
AND NOT EXISTS
(
SELECT
ki110.keyvaluechar,
ki101.keyvaluedate
FROM
itemdata,
keyitem110 ki110 ,
keyitem101 ki101
WHERE --(itemdata.itemnum = ki110.itemnum) --Ticket #
-- ** the problem is here for Date: I need to say Date in Doc Type B doc is not the same as Date in Doc Type A doc using ki101.keyvaluedate)
AND itemdata.itemtypenum = 183) -- this is DOC Type B
你没有
EXISTS
正确使用。在 anEXISTS
中,所选列没有区别,它被完全忽略,甚至不需要名称。这就是为什么我喜欢将语法EXISTS (SELECT 1
全部放在一行上的原因,因为实际上它只是EXISTS
子查询的 not 的额外语法。在您的示例中,您还需要将子查询与外部相关联。
编辑我想我知道你现在想要什么。
如果您遵循逻辑,则需要排除外部中的行,其中内部中存在具有相同票证和日期的匹配行。
笔记:
LEFT JOIN
没有意义,因为您正在过滤它的列,它也可能是一个INNER JOIN
.yyyy-mm-dd
不会因语言和地区而改变。datetime
带有时间分量的半开区间,否则您会得到错误的结果,所以dateCol >= start and dateCol < dayAfterEnd
. 我没有改变这一点,因为你可能有一个date
-only 列。另请注意,根据此,您
LEFT JOIN
的 s 可能应该是INNER JOIN
正如我看到有人提到的那样
NOT IN
,我只会说:NOT IN
通常是一个非常糟糕的主意,因为在可为空的列上它会提供不正确的数据。例如,请参阅此处以了解原因。
--Doc Type A 文档没有匹配的 Doc Type B doc (NOT EXISTS) 且 Ticket # 和 Ticket Date 相同
-- 有类似的文档类型 B 文档具有相同的票号但不同的票证日期我们想忽略这些。
基于这样的数据模型
左连接怎么样?伪代码