2016-05-12 97 views
0

這是我的問題。我在postgres,我有下一個conceptual schema獲得笛卡爾產品

我的目標是顯示遊戲的代碼,名稱的團隊和名稱的玩家誰玩過這個遊戲。我只有表現出遊戲的代碼和名稱的團隊:

select g.code,home_team,t1.name,away_team,t2.name 
from pldata.game g,pldata.team t1,pldata.team t2 
where t1.code = g.home_team 
and t2.code = g.away_team 
order by 1 

我tryed爲得到名字的球員太

select g.code,t.name,p.surname 
from pldata.team t,pldata.player p,pldata.player p2,pldata.game g,pldata.team t2 
where t.code=p.belongs 
and t2.code=p2.belongs 
and t.code=g.home_team 
and t2.code=g.away_team 
order by code 

做到這一點,但使一個笛卡爾乘積和我不不知道爲什麼。任何形式的幫助都很好,所以謝謝你。

+6

切換到現代,明確的JOIN語法,生活將變得更加簡單! – jarlh

+0

將您的選擇列表更改爲'select g.code,t.name,p.surname,t2。名字AS name2,p2.surname AS surname2',你會看到光! – joop

+0

我試過了,我繼續看到笛卡爾產品。 –

回答

0

首先我在工作,不能檢查圖像的你linked.It的更好,當你問這樣的問題總是張貼所有表的數據樣本。

沒有數據,我只能猜測。

您的第一個錯誤是,您使用隱式JOIN語法而不是顯式JOIN語法。這使得您的查詢很難閱讀,從而進行調試和理解。

這是您的查詢中明確語法重寫,你應該始終建立您的SQL是這樣的:

SELECT g.code,g.home_team, t1.name, p1.surname, g.away_team, t2.name, p2.surname 
FROM pldata.game g 
INNER JOIN pldata.team t1 ON t1.code=g.home_team 
INNER JOIN pldata.player p1 ON t1.code=p1.belongs 
INNER JOIN pldata.team t2 ON t2.code=g.away_team 
INNER JOIN pldata.player p2 ON t2.code=p2.belongs 
ORDER BY g.code 

而且因爲有此查詢沒有CROSS JOIN它應該永遠不會返回笛卡爾積。

所以現在的問題是,是團隊多人

如果是的話,那麼你就會有幾行返回一個遊戲,因爲將有2隊的每個球員一行。這可能就是你認爲的笛卡爾產品。

使用顯式連接語法,可以非常容易地調試查詢以瞭解問題(如果有)所在的位置。只需刪除播放器表上的2個連接並重試。

如果它是多人遊戲,並且您希望每場比賽只有一排,但仍然希望所有球員都在結果中,那麼您應該執行GROUP_CONCAT。該表達式在postgress中不受支持,但您可以使用string_agg(the_column, ',')來實現同樣的功能。但是,你只能做的球員concatanation一個團隊:

SELECT g.code, g.home_team, string_agg(p1.surname,',') AS Team1Players 
    FROM pldata.game g 
    INNER JOIN pldata.team t1 ON t1.code=g.home_team 
    INNER JOIN pldata.player p1 ON t1.code=p1.belongs 
    GROUP BY g.code, g.home_team 

該解決方案有兩個隊在一排就是讓2之間的法定的繼承權agreggated GROUP BY查詢,爲每個團隊:

SELECT Team1.code,Team1.home_team, Team1.Team1Players, Team2.away_team, Team2.Team2Players 
FROM  
( 
    SELECT g.code, g.home_team, string_agg(p1.surname,',') AS Team1Players 
    FROM pldata.game g 
    INNER JOIN pldata.team t1 ON t1.code=g.home_team 
    INNER JOIN pldata.player p1 ON t1.code=p1.belongs 
    GROUP BY g.code, g.home_team 
) Team1 
INNER JOIN 
(
    SELECT g.code, g.away_team, string_agg(p2.surname,',') AS Team2Players 
    FROM pldata.game g 
    INNER JOIN pldata.team t2 ON t2.code=g.away_team 
    INNER JOIN pldata.player p2 ON t2.code=p2.belongs 
    GROUP BY g.code, g.away_team 
) Team2 
ON Team1.Code = Team2.code 
ORDER BY Team1.code 

不知道是否所有這些都回答了你的問題,如果我沒有犯一些語法錯誤,但是這個想法是存在的,至少你有一些提示可以進一步移動。

如果我的查詢不起作用或者您需要進一步的幫助,您應該絕對編輯您的問題以添加DLL和數據,以便我們有一個操場。

+0

感謝您的建議托馬斯。這非常有幫助。這是我在stackoverflow上的第二篇文章,我不知道如何去做。關於Joins,我的老師認爲不是這樣,所以他們沒有很好地教給我們。我認爲你正在以sql程序員的身份工作,所以你怎麼看待這個問題。他錯了嗎? –

+0

如果你的意思是你的老師告訴你應該使用implcit連接而不是顯式連接....他應該停止教學。只要對此進行一些Google搜索,那會讓你瞭解他有多糟糕;-) –