2010-05-17 38 views
3

我有PermitHolders数据库(PermitNum = PK)和每个许可证持有人的DetailedFacilities。在tblPermitDetails表中有2列分组记录由子组SQL

  1. PermitNum(外键)
  2. FacilityID(整数外国键查找到设备表)。

一个permitee可以在他们的许可证上有1-29个项目,例如。许可证50可以有一个船坞(FacID 4),铺设的走道(FacID 17)和挡土墙(FacID 20)等。我需要一个SQL过滤器/显示任何东西,所有PERMIT#只有FacID 19,20或28,不是那些加上“x”其他人,......就是那个子集。我已经为此工作了4天,请有人帮我?我已发布到其他BB,但尚未收到任何有用的建议。

由于俄德建议,这里有更多的细节。 tblPermitDetails表没有PK。

比方说,我们有Permitees 1 - 10;许可证1是John Doe,他有一个船坞(FacID 1),一个人行道(FacID 4),一个浮标(FacID 7)和Underbrushing(FacID 19)......这三个记录是许可证1的许可证。许可证2 Sus Brown,她只进行了刷新(FacID 19),许可证3是Steve Toni,他有一个船坞(FacID 1),一个人行道(FacID 4),一个浮标(FacID 7)和一个挡土墙(FacID 20) 。许可证4是Jill Jack,她有Underbrushing(FacID 19)和Retaining Wall(FacID 20)。我可以继续,但我希望你能跟着我。我想要一个SQL(的MS Access),将显示我只允许2 & 4,因为他们有FacIDs 19 & 20任两者或一方或另一方]组合,但不是别的,如许可证1谁拥有# 19,但也有4 & 7.

我希望有所帮助,请说出如果不是。

哦耶,我知道即与例如之间的差因为我40多岁的时候已经写了超过3000页的考古学领域的报告和硕士论文,但是我在这里挣扎于这个SQL中,并且很少关心在敲出请求之前咨询芝加哥风格手册求助。 SO,DON“T是腼腆我的compostion错误!谢谢!

+0

你想要那些只有三个FacID?还是那些有三个FacID的组合? – Loki 2010-05-17 17:30:01

+0

什么是数据库服务器? MS,Oracle,MySql? – Blorgbeard 2010-05-17 17:30:06

+2

@Stacy - 你的问题不是很容易理解,所以你没有得到回应。你能编辑它并添加你想要的数据和输出的例子吗?如果我们能看到这一点,人们就会更容易理解你所需要的东西。 – Oded 2010-05-17 17:33:09

回答

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)) 
+0

我认为这个人做这个工作。 – Garett 2010-05-17 18:06:07

+0

如果它能完成这项工作,为什么你没有接受它作为答案? – 2010-05-20 01:42:20

-1

快速的方式可能是只能看着那些具有完全相同的三场比赛(与内部查询),然后在那些只包括那些有19,20和28.

当然,这是一种蛮力的方法,并不是很优雅,但它有小的好处我可以想到的任何方法都可以很容易地定制到其他各种数值上。

0
SELECT PermitNum 
FROM tblPermitDetails 
WHERE FacilityID IN (19, 20, 28) 
GROUP BY PermitNum 
HAVING COUNT(PermitNum)=3 
+0

这个假设只能有一个与Permitholder相关的设施 – Loki 2010-05-17 17:36:46

-1

好吧,看来我起先不明白的问题。因此,再次:

我将在这里重新通过斯泰西的例子:

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和预期查询的有用索引。

+0

这是行不通的。 PermitNum只能是给定记录的一个值,所以您的查询永远不会返回任何结果。 – dcp 2010-05-17 17:56:03

+0

我已经测试过这一点,它的工作原理。请再检查一次。谢谢 – Marwan 2013-05-05 08:18:48

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) 
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)); 

或者,散文,得到有任何要求的许可证数量,只要存在对PermitNum不在请求列表中没有排PermitNums名单。

同一查询的更优化的版本将是以下几点:

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)); 

这是一个有点难以阅读,但它将涉及较少的“NOT EXISTS”首先做了“独特的”部分子查询。

更新:

大卫-W-芬顿提到NOT EXISTS应避免进行优化的原因。对于一个小桌子,这可能不会多大关系,但你也可以使用COUNT(*)做查询,如果你需要避免NOT EXISTS:

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) 
+0

在Access中避免不存在是一件好事,因为它不可靠地优化,并且通常不会在比较的两侧使用索引。 – 2010-05-27 18:05:33

+0

查看已更新的答案。对于一个小型表格,使用NOT EXISTS可能不会产生任何明显的差异,即使它执行了表格扫描而不是索引查找,但是如果需要的话还有其他方法可以解决问题(尽管我怀疑这个问题会是所有子查询的速度都更快 - 但它可能是提出更优化的起点)。 – 2010-05-28 13:09:44

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 

即我们发现所有与您的标准不符的许可证(他们至少有一个以外的详细信息),然后我们通过左连接和其中的条件找到剩下的所有许可证。

索引设置正确,这应该很快。