2008-10-14 65 views
5

我正在寻找一种方式来依次在结果的行数设置(不是表)。从本质上讲,我开始用类似下面的查询:纯SQL技术的自动编号的结果行集

SELECT id, name FROM people WHERE name = 'Spiewak' 

id s为显然不是一个真正的序列(例如,1, 2, 3, 4)。我需要的是包含这些自动编号的结果集中的另一列。如果必须的话,我愿意使用SQL函数,但我宁愿不使用ANSI规范中的扩展。

平台是MySQL,但是该技术应该是跨平台的,如果在所有可能的(因此避免非标准扩展的愿望)。

回答

9

有你需要订购您的结果有意义的行号。该子查询的WHERE子句需要在WHERE子句或从主查询的ORDER BY主查询的主键匹配

SELECT id, name 
    , (SELECT COUNT(*) FROM people p2 WHERE name='Spiewak' AND p2.id <= p1.id) AS RowNumber 
FROM people p1 
WHERE name = 'Spiewak' 
ORDER BY id 

注:然后你就可以做这样的事情。

SQL Server具有ROW_NUMBER()OVER构造简化,但我不知道如果MySQL有什么特别的东西来解决它。


因为我的岗位在这里被接受的答案,我想还叫出丹Goldstein的反应,这是在方法上非常相似,但采用的是JOIN,而不是一个子查询,常常会表现得更好

+1

这很聪明,但表现必须是可怕的。并不是说我有更好的答案,只是对它的O(n^2)感到不安。 – 2008-10-14 18:30:23

+0

哇!这非常聪明。我甚至不知道你可以使用子查询以这种方式定义res域。 – 2008-10-14 18:30:38

2

没有ANSI标准的方式做到这一点,其中我知道。

在SQL Server中你有哪些可用于在Oracle中,有一个ROWNUM伪列ROW_NUMBER()函数。

在MySQL中,有this technique

+0

他可能更喜欢ROW_NUMBER()来RANK(),但是因为他使用的是MySQL/Ansi,所以这是一个有争议的问题。 – 2008-10-14 18:29:52

7

一个想法,这是非常低效的,但ANSI SQL将与数行数意见符合相同标准的较少ID。我没有测试过这个SQL,它可能不起作用,但它可能不起作用,但类似:

SELECT id, name, sub.lcount 
FROM people outer 
JOIN (SELECT id, COUNT(id) lcount FROM people WHERE name = 'Spiewak' AND id < outer.id GROUP BY id) sub on outer.id = sub.id 
WHERE name = 'Spiewak' 
-1

对于SQL服务器,检查RANK函数。

2

在oracle中我知道你想要做什么,唯一的数据库是做一个子上的数据

select rownum, id , blah, blah 
from (
select id, name FROM people WHERE name = 'Spiewak' 
) 

的基本概念是ROWNUM将评估选择从内部选择返回的结果集。

我希望这可能会指出您可以使用的解决方案。

1

我知道这是一个古老的线程,但我只是现在正在寻找这个答案。我在MySQL中尝试了Dan Goldstein的查询,但它没有像写入那样工作,因为'outer'是一个保留字。然后,我注意到它仍然使用子查询,反正。

所以,我想通了,使用JOIN的一个版本,但没有子查询:

SELECT SUM(IF(p1.id > p2.id, 0, 1)) AS `row`, p2.id, p2.name 
    FROM people p1 JOIN people p2 ON p1.name = p2.name 
    WHERE p1.name = 'Spiewak' 
    GROUP BY p2.id 

这在MySQL 5.1为我工作。对于MySQL来说,GROUP BY p2.id似乎已经足够了。显式的ORDER BY p2.id可以被添加到查询的末尾,但是我得到了相同的结果。