我有一个PermitHolders(PermitNum = PK)的数据库和每个许可证持有人的详细功能。在tblPermitDetails表中有2列
permitee的许可证上可以包含1-29项,e.i。许可证50可以有船坞(FacID 4),铺设走道(FacID 17)挡土墙(FacID 20)等。我需要一个SQL过滤器/显示任何,所有PERMIT #s只有Facids 19,20,或28,不是那些加上“x”其他的......,只是那个子集。我已经为此工作了4天,有人请帮帮我吗?我已经发布到其他BB但没有收到任何有用的建议。
正如Oded所说,这里有更多细节。 tblPermitDetails表没有PK。
假设我们有Permitees 1 - 10;许可证1是John Doe,他有一个船坞(FacID 1),走道(FacID 4),浮标(FacID 7)和Underbrushing(FacID 19)......这些是许可证1的3条记录。许可证2是Sus Brown,她只有刷下(FacID 19),Permit 3是Steve Toni,他有一个船坞(FacID 1),一个走道(FacID 4),一个浮标(FacID 7)和一个挡土墙(FacID 20) 。许可证4是Jill Jack,她有Underbrushing(FacID 19)和挡土墙(FacID 20)。我可以继续,但我希望你跟着我。我想要一个SQL(用于MS Access),它只会向我显示Permits 2& 4因为他们有Facidss 19和amp; 20 [两者之一,或者一个或另一个],但不是许可证,如许可证1,#19,但也有4& 7。
我希望有所帮助,如果没有,请说出来。
哦,是的,我知道ie和eg之间的区别。因为我40多岁时已经写了超过3000页的考古领域报告和一篇硕士论文,但是我真的很沮丧,因为我在努力学习这篇SQL并且不太关心在咨询芝加哥风格手册之前提出的请求。求助。所以,不要对我的构图错误感到羞耻!谢谢你!
答案 0 :(得分:1)
未经测试,但这样的事情怎么样?
SELECT DISTINCT p.PermitNum
FROM tblPermitDetails p
WHERE EXISTS
(SELECT '+'
FROM tblFacility f
WHERE p.FacilityID = f.FacilityID
AND f.facilityID = 19 )
AND EXISTS
(SELECT '+'
FROM tblFacility f
WHERE p.FacilityID = f.FacilityID
AND f.facilityID = 20 )
AND EXISTS
(SELECT '+'
FROM tblFacility f
WHERE p.FacilityID = f.FacilityID
AND f.facilityID = 28 )
AND NOT EXISTS
(SELECT '+'
FROM tblFacility f
WHERE p.FacilityID = f.FacilityID
AND f.facilityID NOT IN (19,20,28) )
答案 1 :(得分:0)
SELECT PermitNum
FROM tblPermitDetails
WHERE FacilityID IN (19, 20, 28)
GROUP BY PermitNum
HAVING COUNT(PermitNum)=3
答案 2 :(得分:0)
我不确定你是否想要19,20,28或19,20,28中的任何一个......而且,这是未经测试的,但如果你想要任何解决方案它应该相当接近
Select
allowed.PermitNum
from
DetailedFacilties allowed
join DetailedFacilities disallowed on allowed.PermitNum != disallowed.PermitNum
where
allowed.FacilityID in (19, 20, 28)
and disallowed.FacilityID not in (19, 20, 28)
答案 3 :(得分:0)
SELECT DISTINCT PermitNum FROM tblPermitDetails t1
WHERE FacilityID IN (19, 20, 28)
AND NOT EXISTS (SELECT 1 FROM tblPermitDetails t2
WHERE t2.PermitNum = t1.PermitNum
AND FacilityId NOT IN (19, 20, 28));
或者,在散文中,获取具有任何所请求的许可证号码的PermitNums列表,只要该PermitNum不存在不在请求列表中的行。
同一查询的更优化版本如下:
SELECT PermitNum FROM (SELECT DISTINCT PermitNum FROM tblPermitDetails
WHERE FacilityID IN (19, 20, 28)) AS t1
WHERE NOT EXISTS (SELECT 1 FROM tblPermitDetails t2
WHERE t2.PermitNum = t1.PermitNum
AND FacilityID NOT IN (19, 20, 28));
阅读起来有点困难,但首先执行“DISTINCT”部分会涉及更少的“NOT EXISTS”子查询。
<强>更新强>
David-W-Fenton提到,出于优化原因,应避免使用NOT EXISTS。对于一个小表,这可能无关紧要,但如果你需要避免NOT EXISTS,你也可以使用COUNT(*)进行查询:
SELECT DISTINCT PermitNum FROM tblPermitDetails t1
WHERE (SELECT COUNT(*) FROM tblPermitDetails t2
WHERE t1.PermitNum = t2.PermitNum
AND FacilityID IN (19, 20, 28))
=
(SELECT COUNT(*) FROM tblPermitDetails t3
WHERE t1.PermitNum = t3.PermitNum)
答案 4 :(得分:0)
(未经测试)
怎么样?select permitnum
from tblPermitDetails t1
left outer join
(Select distinct permitnum from tblPermitDetails where facilityId not in (19, 20, or 28)) t2
on t1.permitnum=t2.permitnum
where t2.permitnum is null
即。我们发现所有与您的标准不符的许可证(他们至少有一个在外面您列出的那些),然后我们通过左连接和标准找到剩下的所有许可证。
索引设置正确,这应该很快。
答案 5 :(得分:-1)
快速方法可能只是查看具有三个匹配(具有内部查询)的那些,然后在那些仅包括具有19,20和28的那些。
当然,这是一种蛮力方法,并不是很优雅。但它具有可理解的小优点。我能想到的任何方法都不容易定制到各种其他值集。
答案 6 :(得分:-1)
好吧,我起初似乎并不理解这个问题。所以,再次:
我将在这里重新创建Stacy的例子:
DECLARE @PermitHolders TABLE
(PermitNum INT NOT NULL,
PermitHolder VARCHAR(20))
DECLARE @tblPermitDetails TABLE
(PermitNum INT,
FacilityID INT)
INSERT INTO @PermitHolders VALUES (1, 'John Doe')
INSERT INTO @PermitHolders VALUES (2, 'Sus Brown')
INSERT INTO @PermitHolders VALUES (3, 'Steve Toni')
INSERT INTO @PermitHolders VALUES (4, 'Jill Jack')
INSERT INTO @tblPermitDetails VALUES (1, 1)
INSERT INTO @tblPermitDetails VALUES (1, 4)
INSERT INTO @tblPermitDetails VALUES (1, 7)
INSERT INTO @tblPermitDetails VALUES (1, 19)
INSERT INTO @tblPermitDetails VALUES (2, 19)
INSERT INTO @tblPermitDetails VALUES (3, 1)
INSERT INTO @tblPermitDetails VALUES (3, 4)
INSERT INTO @tblPermitDetails VALUES (3, 7)
INSERT INTO @tblPermitDetails VALUES (3, 20)
INSERT INTO @tblPermitDetails VALUES (4, 19)
INSERT INTO @tblPermitDetails VALUES (4, 20)
这就是解决方案:
SELECT * FROM @PermitHolders
WHERE (PermitNum IN (SELECT PermitNum FROM @tblPermitDetails WHERE FacilityID IN (19, 20, 28)))
AND (PermitNum NOT IN (SELECT PermitNum FROM @tblPermitDetails WHERE FacilityID NOT IN (19, 20, 28)))
我有一个观察: 你没有提到tblPermitDetails的任何PK。如果不存在,则可能不利于性能。我建议您使用PermitNum和FacilityID(复合键)创建PK,因为这将作为您的PK和预期查询的有用索引。