2010-05-17 53 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 

即我們發現所有與您的標準不符的許可證(他們至少有一個以外的詳細信息),然後我們通過左連接和其中的條件找到剩下的所有許可證。

索引設置正確,這應該很快。