2016-05-09 105 views
0

我有一個Perl程序,它根據用戶從網頁中選擇的「報告」選項來查詢MySQL數據庫以取回結果。如何製作使用另一個查詢結果的單個MySQL查詢

其中一份報告是學生住房建築的所有居住者申請了停車許可證但尚未獲得停車許可證的人員。

當學生申請許可證時,它會在單個表格行中記錄他們的汽車(製造商,型號,年份,顏色等)的細節。每間公寓最多可容納三名學生,每名學生可申請許可證。所以公寓可能有0張許可證,或者1張,2張或3張許可證,具體取決於其中有多少輛汽車。

我希望能夠做的是執行MySQL查詢,查詢每間公寓中有多少人佔用停車許可證,然後根據查詢結果找出許多許可證已經發布。如果發放的許可證數量少於申請數量,則應在結果集中返回該公寓號碼。它不必指定具體的居住者,只是該公寓至少有一個申請許可證的人,但還沒有收到一個。

所以我有兩個表,一個被稱爲occupant_info,它包含各種有關乘客的信息,但相關領域有:

counter (a unique row id) 
parking_permit_1_number 
parking_permit_2_number 
parking_permit_3_number 

當停車證已被分配,它被記錄在適當的parking_permit_#_number field(如果它是乘客頭號的許可證,它將被記錄在parking_permit_1_number等)。

第二個表叫做parking_permits,包含所有的車輛/車主細節(品牌,型號,年份,車主,車主地址等)。它還包含一個引用occupant_info表中計數器的字段。

因此,一個例子是:

occupant_info表

counter | parking_permit_1_number | parking_permit_2_number | parking_permit_3_number 
--------|-------------------------|-------------------------|------------------------ 
1  | 12345     |       | 98765 
2  | 43920     |       | 
3  | 30239     |       | 34233 

parking_permits表

counter | counter_from_occupant_info | permit_1_name | permit_2_name | permit_3_name 
--------|----------------------------|---------------|-----------------|------------------- 
1  |2       | David Jones | James Cameron | Michael Smerconish 
2  |3       | Bill Epps  | Hillary Clinton | Donald Trump 
3  |1       | Joanne Miller |     | Sridevi Gupta 

我想要一個查詢,將首先看一下在多少乘客公寓已申請許可證。這通過計算parking_permits表中的名稱來確定。在該表中,第1行有三個名字,第2行有三個名字,第3行有兩個名字。然後查詢應查看occupant_info表,並從parking_permits表中查看每個counter_from_occupant_info,查看是否發出了相同數量的停車許可證。這可以通過比較非空白字段的數量來確定。

使用上面的數據,查詢將看到下列情況:

parking_permit錶行1

Has counter_from_occupant_info equal to "2" 
Has three names 
The row in occupant_info with counter = "2" has only one permit number issued, 
    so counter_from_occupant_info 2 from parking_permits should be in the result set. 

parking_permit錶行2

Has counter_from_occupant_info equal to "3" 
Has three names 
The row in occupant_info with counter = "3" has only two permit numbers issued, 
    so counter_from_occupant_info 3 from parking_permits should be in the result set. 

parking_permit錶行3

Has counter_from_occupant_info equal to "1" 
Has two names 
The row in occupant_info with counter = "1" has two permit numbers issued, 
    so this row should *not* be in the result set. 

我想過使用ifthencasewhentype logic爲此在一個查詢,但坦率地說不能換我圍​​繞如何做到這一點的頭。

我的想法是這樣的:

SELECT 
CASE WHEN (SELECT counter_from_occupant_info 
      FROM parking_permits 
      WHERE parking_permit_1_name != "" 
       AND parking_permit_2_name != "" 
       AND parking_permit_3_name != "") THEN 
IF (SELECT parking_permit_1_number, 
      parking_permit_2_number, 
      parking_permit_3_number 
    FROM occupant_info 
    WHERE counter = ***somehow reference counter from above case statement--I don't know how to do this*** 

但後來我的頭爆炸,我意識到,我不知道我在做什麼赫克。

任何幫助,將不勝感激。 :-)

Doug 
+3

對不起,但這太長了,任何人都會閱讀。請將其降至核心問題。 –

+2

要回答標題的問題:子查詢 – Rogue

回答

1

你有幾個問題:

  1. 你的居住者表架構是壞的。那裏的情況更糟糕,但它看起來像某個人不明白數據庫是如何構建這張表的。

  2. 您的許可證表格也不好。同樣的道理。

  3. 你根本不知道你在做什麼(開玩笑...開玩笑...)

問題1:

你的居住者表大概應該是兩個表。因爲乘員可能有0-3個許可證(可能更多,我不能從樣本數據中得知),那麼您需要一個表格來記錄乘客的屬性(姓名,身高,性別,年齡,主要氣味,最喜歡的顏色,首次租用日期, 我不知道)。

住戶

OccupantID | favorite TV Show | number of limbs | first name | last name | aptBuilding 

而且......乘客和許可證之間的另一個表的關係:

Occupant_permits現在

OccupantID | Permit ID | status 

...的乘坐者可以有儘可能多的許可證,因爲你可以填入該表格和th之間的關係他們的狀態爲「申請」,或「已授予」或「已撤銷」或您有什麼。

問題2

你的許可信息表是做雙重任務爲好。它包含有關許可證(它的名稱)的信息以及與乘客的關係。既然我們已經有了上面的「Occupant_Permits」表乘員的關係,我們只需要一個許可表來保存許可證的屬性:

許可證

Permit ID | Permit Name | Description | etc.. 

問題3

既然你有一個正確的模式,對象在他們自己的表(佔用者,許可證,佔用者和許可證關係)中的對象,您的查詢以獲得至少有一個申請,但尚未收到許可證的公寓的列表將會:

SELECT 
    COUNT(DISTINCT o.AptBuilding) 
FROM 
    occupants as o 
    INNER JOIN occupants_permit as op 
     ON o.occupant_id = op.occupant_id 
    INNER JOIN permits as p 
     ON op.permit_id = p.permit_id 
WHERE 
    op.Status = "Applied" 

這是很好的和簡單,你不是靠CASEUNION或數比較或任何花哨的東西。只是很好的直接連接和一個簡單的WHERE子句。這將是快速查詢,並沒有有趣的業務。


因爲你的模式是不是很大,爲了得到類似的東西,你需要充分利用兩種UNION查詢的堆棧的許多permit_N_領域到一個單一的領域,並運行類似上面的查詢的東西,或者你必須使用情況的相當數量/ IF語句:

SELECT DISTINCT p.pCounter 
FROM 
    (
     SELECT 
      counter as Ocounter 
      CASE WHEN parking_permit_1_number IS NOT NULL THEN 1 ELSE 0 END 
      + 
      CASE WHEN parking_permit_2_number IS NOT NULL THEN 1 ELSE 0 END 
      + 
      CASE WHEN parking_permit_3_number IS NOT NULL THEN 1 ELSE 0 END AS permitCount 
     FROM occupant_info 
    ) as o 
    LEFT OUTER JOIN 
    (
     SELECT 
      counter_from_occupant_info as pCounter 
      CASE WHEN parking_permit_1_name IS NOT NULL THEN 1 ELSE 0 END 
      + 
      CASE WHEN parking_permit_2_name IS NOT NULL THEN 1 ELSE 0 END 
      + 
      CASE WHEN parking_permit_3_Name IS NOT NULL THEN 1 ELSE 0 END AS permitPermitCount 
    ) as p ON o.Ocounter = p.Pcounter 

WHERE p.permitCounter > o.PermitCount 

我不是100%確信是你在尋找什麼,因爲你的模式是混淆了,你必須在多個對象單桌和一切都是旋轉的,但是......它應該讓你進入球場。

這也會慢得多。有中間結果集,CASE語句和數學,所以不要指望MySQL以毫秒爲單位吐出它。

+0

非常感謝JNevill。不幸的是,我沒有足夠的時間來重寫構建在這個數據庫結構上的(非常大的)代碼庫,所以糟糕的表格佈局將不得不暫時停留。您在評論結尾寫下的查詢與我所需要的一致。我正在嘗試爲了我的目的調整它。 *非常感謝您的幫助! –

相關問題