2011-07-27 12 views
3

我與小馬的細節的表的數據庫,另一個聯繫人(業主和飼養者),和其他然後幾個小表的參數(顏色,縣,地區代碼等)的細節。給我的現有小馬配置文件的列表,用他們給出的各種細節,我用下面的查詢:使用聯接,分組和子查詢,哦,我的!

SELECT * 
    FROM profiles 
     INNER JOIN prm_breedgender 
      ON profiles.ProfileGenderID = prm_breedgender.BreedGenderID 
     LEFT JOIN contacts 
      ON profiles.ProfileOwnerID = contacts.ContactID 
     INNER JOIN prm_breedcolour 
      ON profiles.ProfileAdultColourID = prm_breedcolour.BreedColourID 
    ORDER BY profiles.ProfileYearOfBirth ASC $limit 

在上面的例子中,「配置文件」表是我的主表(持有小馬信息) '聯繫人'是第二重要的,因爲它的所有者和育種者信息。較小的參數表可以通過它們的prm_前綴來標識。上述查詢工作正常,但我想做更多。

第一個大問題是,我想GROUP結果按性別:公馬,母馬,閹馬...我用< < GROUP BY prm_breedgender.BreedGender >>或< < GROUP BY ProfileBreedGenderID >>我的ORDER BY之前行,但只會返回所有可用配置文件中的兩個結果。我已經閱讀了這個,並且顯然需要重新組織我的查詢以適應我的主SELECT子句中的GROUP。然而,如何做到這一點,讓我感到困惑。在這裏一步一步的幫助將是非常可觀的。

由於上述再注 - 您可能已經注意到在我的查詢結束的$限制變種。這是分頁,我想保留的一個功能。但我不認爲這是一個問題。

我次要的問題更多的是一種組織之一。你可以看到我已經從聯繫人表拉着我的主人信息在這裏:

LEFT JOIN contacts 
     ON profiles.ProfileOwnerID = contacts.ContactID 

我可以添加其他的規定:

 AND profiles.ProfileBreederID = contacts.ContactID 

具有能夠列出一個小馬的業主和飼養員的意圖,哪裏的信息都可用。我不知道如何回顯這個信息,因爲$ row ['ContactName']可以適用於擁有者或育種者的能力。

這是簡單地運行兩個查詢,而不是一個的情況下?爲查詢的第一次運行分配一個變量$ foo,然後完全運行另一個單獨的查詢並將$ bar分配給這些結果?或者是有一個更聰明的方法在一個查詢中完成所有操作(例如$ row ['ContactName']第一次迭代,$ row ['ContactName']第二次迭代)?建議在這裏將不勝感激。

,這就是它!我儘可能地保持清晰,並且非常感謝您提供的所有幫助或建議。提前致謝。

############################################### ###########################編輯

我的查詢目前已達就是,通過Cularis和Symcbean提供汞合金:

SELECT * 
     FROM (
      profiles 
      INNER JOIN prm_breedgender 
       ON profiles.ProfileGenderID = prm_breedgender.BreedGenderID 
      LEFT JOIN contacts AS owners 
       ON profiles.ProfileOwnerID = owners.ContactID 
      INNER JOIN prm_breedcolour 
       ON profiles.ProfileAdultColourID = prm_breedcolour.BreedColourID 
      ) 
     LEFT JOIN contacts AS breeders 
      ON profiles.ProfileBreederID = breeders.ContactID 
     ORDER BY prm_breedgender.BreedGender ASC, profiles.ProfileYearOfBirth ASC $limit 

它的工作原理是按照我的希望排列結果:按年齡和性別進行排列。但是,我似乎無法得到別名'工作在聯繫人查詢(飼養者和所有者)。沒有錯誤顯示,也沒有任何業主或飼養員。任何進一步的澄清將非常感激。

P.s.我放棄了Symcbean示例給出的最後一個LEFT JOIN的別名,因爲我無法得到由此產生的ORDER BY語句爲我工作 - 我自己的錯,我確定。儘管如此,它現在可以工作,儘管這可能是導致聯繫人查詢問題的原因。

+0

/我想知道爲什麼OMG小馬沒有迴應! :http://stackoverflow.com/users/135152/omg-ponies – symcbean

回答

0

這本來是有益的,如果你提供的表結構的細節和近似數的行。對於SELECT也使用'*'是一個混亂的做法 - 並且以後會導致你的問題(見下文)。

這是什麼版本的MySQL?

apparantly需要重新安排我的查詢到我的主要SELECT子句中容納GROUP

不一定因爲V4(?IIRC),你可以只換你的查詢在鞏固選擇(但移動極限入外選擇:

SELECT ProfileGenderID, COUNT(*) 
FROM (
[your query without the LIMIT] 
) ilv 
GROUP BY ProfileGenderID 
LIMIT $limit; 

(注意不能ORDER BY ilv.ProfileYearOfBirth,因爲它不是通過表達選擇的列/組)

您在prm_breedgender中有多少記錄/列?它只是種馬,馬雷斯,格林斯...?你認爲這份名單可能會改變嗎?你有多性別的小馬?我懷疑這個域會更好地表示在配置文件表中的枚舉。

具有能夠列出一個小馬的業主和飼養員的意圖,

使用貴方提出的代碼,你將只能得到返回這裏的主人和飼養員都是一樣的情況下!您需要添加具有不同別名的聯繫人表格的第二個實例以將其全部獲取,例如

SELECT * 
FROM (
    SELECT * 
    FROM profiles 
    INNER JOIN prm_breedgender 
     ON profiles.ProfileGenderID = prm_breedgender.BreedGenderID 
    LEFT JOIN contacts ownerContact 
     ON profiles.ProfileOwnerID = ownerContact.ContactID 
    INNER JOIN prm_breedcolour 
     ON profiles.ProfileAdultColourID = prm_breedcolour.BreedColourID 
) ilv LEFT JOIN contacts breederContact 
    ON ilv.ProfileBreederID = breederContact.ContactID 
ORDER BY ilv.ProfileYearOfBirth ASC $limit 
+0

是的,使用'*'顯然是錯誤的。我會改變這一點 - 我只是覺得它更簡單,真的。我的版本是5.0.91(我認爲)。您的查詢稍微超出我的意思我很害怕 - 什麼是ilv? – Eamonn

+0

ilv是他給內部選擇的別名。您可以省略表格定義/名稱後面的「AS」來定義別名。 – Jacob

+0

okaaayyy。因此,別名可以應用於選擇,而不僅僅是表格。好東西!所以。 SELECT ALL FROM <<原始查詢>> LEFT JOIN到<< secondary query >>然後ORDER BY。這裏的ORDER BY是否等同於Cularis的答案中給出的ORDER BY? – Eamonn

2

GROUP用SQL術語表示在一組條目上使用聚合函數。我想你想要的是按性別排序:

ORDER BY prm_breedgender.BreedGender ASC, profiles.ProfileYearOfBirth ASC $limit 

這將輸出所有的種馬等相鄰。

也得到飼養員接觸,你需要再次與聯繫人表的加入,使用別名:

LEFT JOIN contacts AS owners 
      ON profiles.ProfileOwnerID = owners.ContactID 

LEFT JOIN contacts AS breeders 
      ON profiles.ProfileBreederID = breeders.ContactID 
+0

哦哇 - 那簡短又甜美!非常感謝。就在別名上「 - 雖然解決了作爲單獨實體問題的查詢,那麼我怎樣才能將結果作爲單獨的實體進行迴響呢?即$ row ['ContactName']是否仍然在混合結果中輸出? – Eamonn

+0

您不能僅使用「聯繫人名稱」,因爲該名稱具有隱蔽性。您必須在前面使用別名的名稱:'owner.ContactName'和'breeders.ContactName' – Jacob

+0

Ahhhhh - so $ row ['owners.ContactName']? – Eamonn

2

要進一步擴展@cularis所述的內容,group by將聚合降至「分組」標準的最低級別。例如,我沒有按照您的具體表格做,但您會看到影響。假設你想顯示按Breed分組的頁面。然後,用戶挑選一個品種,他們可以看到該品種的所有條目。

PonyID ProfileGenderID Breeder 
1  1     1 
2  1     1 
3  2     2 
4  3     3 
5  1     2 
6  1     3 
7  2     3 

Assuming your Gender table is a lookup where ex: 
BreedGenderID Description 
1    Stallion 
2    Mare 
3    Geldings 

SELECT * FROM 型材 INNER JOIN prm_breedgender ON profiles.ProfileGenderID = prm_breedgender。BreedGenderID

select 
     BG.Description, 
     count(*) as CountPerBreed 
    from 
     Profiles P 
     join prm_BreedGender BG 
      on p.ProfileGenderID = BG.BreedGenderID 
    group by 
     BG.Description 
    order by 
     BG.Description 

會導致類似(計數只是巧合順序)

Description CountPerBreed 
Geldings  1 
Mare   2 
Stallion  4 

變化 「ORDER BY」 條款 「以便通過CountsPerBreed DESC」(降序),你會得到

Description CountPerBreed 
Stallion  4 
Mare   2 
Geldings  1 

擴大,如果你想每飼養員被分解的聚合......這是由不骨料(如MIN(),MAX(),AV萬物組最佳實踐G(),COUNT(),SUM()等)

select 
     BG.Description, 
     BR.BreaderName, 
     count(*) as CountPerBreed 
    from 
     Profiles P 

     join prm_BreedGender BG 
      on p.ProfileGenderID = BG.BreedGenderID 

     join Breeders BR 
      on p.Breeder = BR.BreaderID 
    group by 
     BG.Description, 
     BR.BreaderName 
    order by 
     BG.Description 

會導致類似(計數只是巧合順序)

Description BreaderName CountPerBreed 
Geldings  Bill   1 
Mare   John   1 
Mare   Sally  1 
Stallion  George  2 
Stallion  Tom   1 
Stallion  Wayne  1 

正如你所看到的,更多的粒度您提供對於羣組來說,每個級別的聚合更小。

另外,您的加入條件顯然可以從您提供的內容中理解。希望這個示例清楚地說明了查詢過程將做什麼。你的團隊不必與最終訂單一樣......它只是常見的看到,所以有人看着結果並不是想要猜測數據是如何組織的。

在您的示例中,您在出生年份之前有一個訂單。在進行聚合時,你永遠不會有一個單一小馬的特定出生年份,以便按......排序,除非......你將YEAR(ProfileYearOfBirth)包括爲BirthYear作爲一列,並將其包括在你的組中。 ..例如有100只1歲的小馬和37歲的特定品種的2歲幼鴿。

+0

這真的很棒 - 非常有幫助!謝謝! – Eamonn