停止SQL在JOIN中返回两次相同的结果

时间:2012-08-31 14:53:50

标签: sql

我已经将几个表连接在一起以获取我想要的数据,但由于我是SQL的新手,我无法弄清楚如何多次停止返回数据。

她是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个表,但为了简单起见,我将它们遗漏了。

4 个答案:

答案 0 :(得分: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中的一行,你应该选择哪一行?是否应删除一个,或者您是否有其他逻辑/条件可用于选择其中一个?

答案 1 :(得分:0)

更改此

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

到此

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

<强>更新

有些人对使用隐式连接表示法非常敏感。为了安抚这些人并作为更好的实践,您应该使用明确的JOIN陈述。

答案 2 :(得分:0)

尝试使用group by;

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;

答案 3 :(得分: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

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