2012-08-31 104 views
0

我已經將幾個表連接在一起以獲取我想要的數據,但由於我是SQL新手,我無法弄清楚如何停止多次返回數據。停止SQL在JOIN中返回兩次相同的結果

她的SQL語句;

SELECT 
    T.url, 
    T.ID, 

    S.status, 
    S.ID, 

    E.action, 
    E.ID, 
    E.timestamp 

FROM tracks T, status S, events E 
WHERE S.ID AND T.ID = E.ID 

ORDER BY E.timestamp DESC 

返回的數據是這樣的;

+----------------------------------------------------------------+ 
| URL | ID | Status | ID | action    | ID | timestamp | 
+----------------------------------------------------------------+ 
| T.1 | 4 | hello | 4 | has uploaded a track | 4 | time  | 
| T.2 | 3 | bye | 3 | has some news  | 3 | time  | 
| t.1 | 4 | more | 4 | has some news  | 4 | time  | 
+----------------------------------------------------------------+ 

這是一個非常基本的例子,但確實概述了會發生什麼。如果您查看第三行,則在有不同狀態時重複該URL。

這是我希望發生的;

+-------------------------------------------------------+ 
| URL or Status | ID | action    | timestamp | 
+-------------------------------------------------------+ 
| T.1   | 4 | has uploaded a track | time  | 
| hello   | 3 | has some news  | time  | 
| bye   | 4 | has some news  | time  | 
+-------------------------------------------------------+ 

請注意,當動作已上載曲目時,會顯示網址(本例中模擬曲目爲T.1)。這個非常重要。事件表中的動作插入狀態或軌道插入的觸發器中。如果插入新曲目,則操作是「已上傳曲目」,並且您猜測它的狀態。此時,ID和時間戳也被插入到事件表中。

注意:有更多的表格進入查詢,其實有3個,但爲簡單起見,我已將其留出。

+1

由於您是SQL新手,您應該知道隱式連接是SQL反模式,您應該學會使用顯式連接。 – HLGEM

回答

2

不要使用20年過時的語法。儘管許多RDBMS支持FROM a, b, c樣式語法,但它已被我所使用的所有系統所棄用。 (我還沒有和一切工作,但它確實強烈建議不要使用這種風格。)

而是使用ANSI-92標準JOIN語法。然後,它更難把事情搞錯了......

SELECT 
    * 
FROM 
    status S 
INNER JOIN 
    tracks T 
    ON T.ID = S.ID 
INNER JOIN 
    events E 
    ON E.ID = S.ID 
ORDER BY 
    E.timestamp DESC 

而且,你比如數據表明,你必須在表S中的下列...

Status | ID 
--------+---- 
hello | 4 
bye | 3 
more | 4 

ID = 4有兩行。如果你真的想讓T中的每一行只加入S中的一行,你應該選擇哪一行?是否應該刪除一個,還是你有其他邏輯/條件可以用來挑選其中的一個?

+0

如果我發誓,我會讓你百萬次。對於使用implict語法的strill而言,這實際上並不是理由。但是,它在所有系統中都不被棄用。在SQL Server中,只有外部聯接implict語法已被棄用(並且它始終無法正常工作,這是原因的一部分)。對於新手來說,SQl需要理解連接,並且顯式連接對於初學者來說更有可能是不正確的。 – HLGEM

+0

'從a,b,c'仍然被教導和使用。這也不能解決OP的期望結果。 – Kermit

+0

感謝您的信息,沒有意識到它已被棄用。我正在使用的教程是使用舊的東西。因爲它全部在新聞饋送中返回,所以應該返回該ID中的每個狀態,然後按時間戳排序。 –

0

更改此

WHERE S.ID AND T.ID = E.ID 

對此

WHERE S.ID = E.ID AND T.ID = E.ID 

更新

有一些人是感情豐沛的有關使用隱式連接符號極爲敏感。爲了安撫這些人並作爲更好的做法,您應該使用明確的JOIN陳述。

+0

這並沒有達到預期的效果。不太清楚如何解釋它,但請看看結果應該是什麼樣子來解釋什麼需要發生 –

+0

嘗試'WHERE T.ID = S.ID和S.ID = E.ID' – Kermit

+0

同樣的事情發生。 –

0

嘗試使用組通過;

SELECT T1.url, T1.id, S1.estatus, S1.id, E1.action, E1.id, E1.timestamp FROM t T1, s S1, e E1 WHERE S1.id AND T1.id = E1.id GROUP BY S1.id ORDER BY E1.timestamp DESC; 
0

感謝所有的答案,他們幫助了很多。我做了一個查詢,它可以在PHP中使用if語句來操作和處理結果。

這是它;

SELECT 
T.url AS track_url, 

S.status, 

E.action, 
E.ID, 
E.timestamp, 

A.name, 
A.url AS artist_url 

FROM events E 

LEFT JOIN 
TRACKS T 
ON T.ID = E.ID AND E.action = 'has uploaded a track.' 

LEFT JOIN 
STATUS S 
ON S.ID = E.ID AND E.action = 'has some news.' 

LEFT JOIN 
ARTISTS A 
ON A.ID = E.ID 

ORDER BY E.timestamp DESC 

它的結果是大量的NULL列,但是這很好,因爲它的工作原理!如果ID尚未上傳軌道,則相關列爲NULL,同樣適用於查詢的其他位。 ID不會重複,因爲只有事件表中的ID被選中。

如果您發現任何我可能忽略的問題,請大聲呼喊!