LEFT OUTER JOIN 和 NOT EXISTS 查询
Posted
技术标签:
【中文标题】LEFT OUTER JOIN 和 NOT EXISTS 查询【英文标题】:LEFT OUTER JOIN and NOT EXISTS query 【发布时间】:2013-03-14 12:38:59 【问题描述】:我很难使用复杂的连接,我需要连接两次相同的两个表,并确保每次只使用特定记录(最近的记录)完成连接。
SELECT c.collection_id AS collections,
s.strat_id AS StrategyId,
s.strat_version AS StrategyVersion,
ssb.side_ordering AS SSB_SO,
ssb2.side_ordering AS SSB2_SO,
Invoice1.invoice_id AS Inv1ID,
Invoice2.invoice_id AS Inv2ID,
Invoice1.printeddate AS Inv1PrintedDate,
Invoice2.printeddate AS Inv2PrintedDate
FROM dbo.collections AS c
INNER JOIN dbo.strategies AS s
ON c.collection_id = s.collection_id
INNER JOIN dbo.side_strat_brkrgs AS ssb
ON s.collection_id = ssb.collection_id
AND s.strat_id = ssb.strat_id
AND s.strat_version = ssb.strat_version
INNER JOIN dbo.strat_sides AS ss
ON ss.strat_side_id = ssb.strat_side_id
LEFT OUTER JOIN dbo.side_strat_brkrgs AS ssb2
ON ssb2.collection_id = ssb.collection_id
AND ssb2.strat_id = ssb.strat_id
AND ssb2.strat_version = ssb.strat_version
AND ssb2.side_ordering <> ssb.side_ordering
INNER JOIN dbo.strat_sides AS ss2
ON ss2.strat_side_id = ssb2.strat_side_id
LEFT OUTER JOIN dbo.newinvoiceitem AS InvoiceItem1
ON ssb.collection_id = InvoiceItem1.collection_id
AND ssb.side_ordering = InvoiceItem1.side_ordering
AND s.strat_id = InvoiceItem1.strat_id
LEFT OUTER JOIN dbo.newinvoice AS Invoice1
ON Invoice1.invoice_id = InvoiceItem1.invoice_id
LEFT OUTER JOIN dbo.newinvoiceitem AS InvoiceItem2
ON ssb2.collection_id = InvoiceItem2.collection_id
AND ssb2.side_ordering = InvoiceItem2.side_ordering
AND s.strat_id = InvoiceItem2.strat_id
LEFT OUTER JOIN dbo.newinvoice AS Invoice2
ON Invoice2.invoice_id = InvoiceItem2.invoice_id
WHERE NOT EXISTS (SELECT 1
FROM dbo.newinvoiceitem tempInvoiceItem1
INNER JOIN dbo.newinvoice AS tempInvoice1
ON tempInvoice1.invoice_id =
tempInvoiceItem1.invoice_id
WHERE tempInvoiceItem1.collection_id = ssb.collection_id
AND ssb.side_ordering = tempInvoiceItem1.side_ordering
AND s.strat_id = tempInvoiceItem1.strat_id
AND s.strat_version = tempInvoiceItem1.strat_version
AND tempInvoice1.printeddate > Invoice1.printeddate)
AND NOT EXISTS (SELECT 1
FROM dbo.newinvoiceitem tempInvoiceItem2
INNER JOIN dbo.newinvoice AS tempInvoice2
ON tempInvoice2.invoice_id =
tempInvoiceItem2.invoice_id
WHERE
tempInvoiceItem2.collection_id = ssb2.collection_id
AND ssb2.side_ordering = tempInvoiceItem2.side_ordering
AND s.strat_id = tempInvoiceItem2.strat_id
AND s.strat_version = tempInvoiceItem2.strat_version
AND tempInvoice2.printeddate > Invoice2.printeddate)
AND c.collection_id = 16447
我得到以下结果:
16447 1 3 1 0 3785 3183 2010-05-06 17:52:00 2010-05-06 17:52:00
16447 1 3 1 0 3785 4033 2010-05-06 17:52:00 2010-05-10 16:32:00
16447 1 3 1 0 4137 3183 2010-05-20 17:08:00 2010-05-06 17:52:00
16447 1 3 1 0 4137 4033 2010-05-20 17:08:00 2010-05-10 16:32:00
虽然我实际上只期待最后一行。我哪里错了?
如您所见,我不能使用 MAX() 来检索最高记录,因为我需要通过 JOIN 查找另一个属性,并且我不得不使用 NOT EXIST
【问题讨论】:
如果这是针对大型数据集,为了优化和可扩展性,我会考虑绕过左连接并将其分解为更小更易于管理的块 :) 你能稍微处理一下缩进吗?现在不可读。 您的查询有点复杂,我无法理解。通常,当查找最近的记录时,会使用 MAX() 来选择最高的发票编号或最迟日期。 您的第一个查询无法解析...并使用this 格式化您的查询... @Edmondo1984 在逻辑上而不是编辑器包装它们的位置插入换行符 - 在 FROM 下缩进表和连接,在 SELECT 下缩进列,使连接的ON
条件在视觉上与加入他们所属的行列。
【参考方案1】:
试试这个谓词
WHERE EXISTS (SELECT 1
FROM dbo.newinvoiceitem tempInvoiceItem1
INNER JOIN dbo.newinvoice AS tempInvoice1
ON tempInvoice1.invoice_id = tempInvoiceItem1.invoice_id
WHERE tempInvoiceItem1.collection_id = ssb.collection_id
AND ssb.side_ordering = tempInvoiceItem1.side_ordering
AND s.strat_id = tempInvoiceItem1.strat_id
HAVING MAX(tempInvoice1.printeddate) = Invoice1.printeddate
OR Invoice1.printeddate IS NULL
)
AND EXISTS (SELECT 1
FROM dbo.newinvoiceitem tempInvoiceItem2
INNER JOIN dbo.newinvoice AS tempInvoice2
ON tempInvoice2.invoice_id = tempInvoiceItem2.invoice_id
WHERE tempInvoiceItem2.collection_id = ssb2.collection_id
AND ssb2.side_ordering = tempInvoiceItem2.side_ordering
AND s.strat_id = tempInvoiceItem2.strat_id
HAVING MAX(tempInvoice2.printeddate) = Invoice2.printeddate
OR Invoice2.printeddate IS NULL
)
AND c.collection_id = 16447
或
WHERE EXISTS (SELECT 1
FROM dbo.newinvoiceitem tempInvoiceItem1
INNER JOIN dbo.newinvoice AS tempInvoice1
ON tempInvoice1.invoice_id = tempInvoiceItem1.invoice_id
WHERE tempInvoiceItem1.collection_id = ssb.collection_id
AND ssb.side_ordering = tempInvoiceItem1.side_ordering
AND s.strat_id = tempInvoiceItem1.strat_id
HAVING MAX(tempInvoice1.printeddate) = Invoice1.printeddate
)
AND EXISTS (SELECT 1
FROM dbo.newinvoiceitem tempInvoiceItem2
INNER JOIN dbo.newinvoice AS tempInvoice2
ON tempInvoice2.invoice_id = tempInvoiceItem2.invoice_id
WHERE tempInvoiceItem2.collection_id = ssb2.collection_id
AND ssb2.side_ordering = tempInvoiceItem2.side_ordering
AND s.strat_id = tempInvoiceItem2.strat_id
HAVING MAX(tempInvoice2.printeddate) = Invoice2.printeddate
)
AND c.collection_id = 16447 OR Invoice1.printeddate IS NULL
OR Invoice2.printeddate IS NULL
【讨论】:
这会为我返回一个空集:( 39 分钟前编辑的最后一个版本有效。你能解释一下原因吗? 我认为 EXISTS() 运算符 s.strat_version = tempInvoiceItem1.strat_version 中的条件过多,因为对于行数据比较,我们需要相同的数据集。 回到主题,这会将左外连接变成内连接...我也想要NULL 没问题;) 只需添加条件 Invoice1.printeddate IS NULL/Invoice2.printeddate IS NULL。答案已更新以上是关于LEFT OUTER JOIN 和 NOT EXISTS 查询的主要内容,如果未能解决你的问题,请参考以下文章
MySQL 数据库中 left outer join 和 left join 啥区别?
SQL Server 中的 LEFT JOIN 与 LEFT OUTER JOIN
KTable vs GlobalKTable 和 left Join() vs outer Join() 有啥区别?
Inner Join, Left Outer Join和Association的区别
CROSS JOIN和INNER JOIN,LEFT JOIN,RIGHT JOIN,OUTER JOIN之间的区别[重复]
left join ,right join ,inner join,outer join,union all,union有啥区别?怎么用?