我有以下示例多对多关系:
我正在构建一个UI,允许用户选择多个文档进行批处理。每批可以有很多文件;每个文档只能在一个批处理中,除非批处理无效。
在此UI上,我需要显示可用的文档。如果文档是:
,则文档被视为可用示例数据:
CREATE TABLE tmpDocument (DocumentID INT, IsVoid BIT)
INSERT INTO tmpDocument VALUES (1,1)
INSERT INTO tmpDocument VALUES (2,0)
INSERT INTO tmpDocument VALUES (3,0)
INSERT INTO tmpDocument VALUES (4,0)
INSERT INTO tmpDocument VALUES (5,0)
INSERT INTO tmpDocument VALUES (6,0)
INSERT INTO tmpDocument VALUES (7,0)
INSERT INTO tmpDocument VALUES (8,0)
INSERT INTO tmpDocument VALUES (9,0)
CREATE TABLE tmpBatch (BatchID INT, IsVoid BIT)
INSERT INTO tmpBatch VALUES (1,0)
INSERT INTO tmpBatch VALUES (2,1)
INSERT INTO tmpBatch VALUES (3,0)
CREATE TABLE tmpBatchDocument (BatchDocumentID INT, BatchID INT, DocumentID INT)
INSERT INTO tmpBatchDocument VALUES (1,1,2)
INSERT INTO tmpBatchDocument VALUES (2,1,3)
INSERT INTO tmpBatchDocument VALUES (3,2,4)
INSERT INTO tmpBatchDocument VALUES (4,2,5)
INSERT INTO tmpBatchDocument VALUES (5,3,6)
INSERT INTO tmpBatchDocument VALUES (6,3,7)
INSERT INTO tmpBatchDocument VALUES (7,3,8)
文档
DocumentID---IsVoid
1------------1-----
2------------0-----
3------------0-----
4------------0-----
5------------0-----
6------------0-----
7------------0-----
8------------0-----
9------------0-----
批量
BatchID------IsVoid
1------------0-----
2------------1-----
3------------0-----
BatchDocument
BatchDocumentID-----BatchID------DocumentID
1-------------------1------------2---------
2-------------------1------------3---------
3-------------------2------------4---------
4-------------------2------------5---------
5-------------------3------------6---------
6-------------------3------------7---------
7-------------------3------------8---------
要查找可用的文档,我想出了这个T-SQL查询:
SELECT a.DocumentID
FROM tmpDocument a
LEFT JOIN tmpBatchDocument b ON a.DocumentID = b.DocumentID
LEFT JOIN tmpBatch c ON b.BatchID = c.BatchID
WHERE (
b.DocumentID IS NULL
AND a.IsVoid = 0
)
OR (c.IsVoid = 1)
查询正确返回:
DocumentID
4
5
9
文件1被排除在外,因为它无效;不包括文档2,3,6,7和8,因为它们是批处理的,批处理没有作废;包含文档4和5,因为虽然它们是批处理的,但批处理已经无效;包含文件9是因为它没有空白且没有批处理
现在,让我们选择文档4和5,然后将它们添加到新批处理中。
BatchID------IsVoid
1------------0-----
2------------1-----
3------------0-----
4------------0-----
BatchDocumentID-----BatchID------DocumentID
1-------------------1------------2---------
2-------------------1------------3---------
3-------------------2------------4---------
4-------------------2------------5---------
5-------------------3------------6---------
6-------------------3------------7---------
7-------------------3------------8---------
8-------------------4------------4---------
9-------------------4------------5---------
运行相同的查询会返回相同的结果:
DocumentID
4
5
9
由于文件4和5现在与非无效批次相关联,我预计它们将被排除在结果之外,并且仅显示文件9。显然,这没有发生。
如何重写此查询以显示仅与无效批次关联的文档,但如果它们也与无效批处理关联,则将其排除?
答案 0 :(得分:0)
SELECT a.DocumentID
FROM tmpDocument a
LEFT JOIN tmpBatchDocument b ON a.DocumentID = b.DocumentID
LEFT JOIN tmpBatch c ON b.BatchID = c.BatchID
WHERE (
b.DocumentID IS NULL
AND a.IsVoid = 0 --WHY?
)
OR (c.IsVoid = 1
AND NOT EXISTS (select * from c2 where c2.batchID = (select batchID from b2 where b2.DocumentID=a.documentID) AND c2.isVoid=0)
)
编辑回答包含NOT EXISTS。现在已经阅读了您的完整问题,这就是我认为您需要排除那些与文档关联的非空批处理的记录。
答案 1 :(得分:0)
使用COUNT
和HAVING
:
SELECT d.DocumentID
FROM tmpDocument d
LEFT JOIN tmpBatchDocument bd
ON bd.DocumentID = d.DocumentID
LEFT JOIN tmpBatch b
ON b.BatchID = bd.BatchID
WHERE
d.IsVoid = 0
GROUP BY d.DocumentID
HAVING
COUNT(bd.BatchDocumentID) = 0
OR COUNT(CASE WHEN b.IsVoid = 0 THEN 1 END) = 0
WHERE
条款显然会排除无效文件。 HAVING
子句中的第一个条件搜索未批处理的文档,第二个条件将搜索批处理但批处理无效的文档。