2012-08-31 65 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被选中。

如果您发现任何我可能忽略的问题,请大声呼喊!