SQL查询的特殊顺序

时间:2009-02-09 23:18:18

标签: sql mysql sql-order-by

我需要显示由某个数字列排序的数据库表中的记录列表。该表如下所示:

CREATE TABLE  items (
  position int NOT NULL,
  name varchar(100) NOT NULL,
);
INSERT INTO items (position, name) VALUE
(1, 'first'),
(5, 'second'),
(8, 'third'),
(9, 'fourth'),
(15, 'fifth'),
(20, 'sixth');

现在,列表的顺序应根据用户提供的参数而改变。此参数指定首先出现的记录如下:

position = 0
order should be = 1, 5, 8, 9, 15, 20

position = 1
order should be = 20, 1, 5, 8, 9, 15

position = 2
order should be = 15, 20, 1, 5, 8, 9

换句话说,最后一条记录成为第一条,依此类推。你能想到在SQL中这样做的方法吗?

我正在使用MySQL,但任何SQL数据库中的示例都可以。

由于

7 个答案:

答案 0 :(得分:2)

您确定要在SQL中执行此操作吗?

对我而言,这听起来应该将结果加载到某种数据集中,然后根据需要重新排序,或者将起点定位在正确的位置。

可能使用链表。

答案 1 :(得分:2)

了解这对您有何帮助。使用通用SQL,因此它也应该对MySql(未经测试)有效。

DECLARE @user_sort INTEGER
SET @user_sort = 0

SELECT position, name FROM 
(
  SELECT I1.position, I1.name, COUNT(*) AS rownumber, (SELECT COUNT(*) FROM items) AS maxrows
  FROM items I1, items I2
  WHERE I2.position <= I1.position
  GROUP BY I1.position, I1.name
) Q1
ORDER BY 
  CASE WHEN maxrows - rownumber < (@user_sort % maxrows) THEN 1 ELSE 2 END, position

注意: *如果用户提供的排序索引大于行计数,则该值将换行到有效范围内。要删除此功能,请从ORDER BY中删除“%maxrows”。

<强> 结果:

SET @user_sort = 0

position    name
1   first
5   second
8   third
9   fourth
15  fifth
20  sixth

SET @user_sort = 1

position    name
20  sixth
1   first
5   second
8   third
9   fourth
15  fifth

SET @user_sort = 2

position    name
15  fifth
20  sixth
1   first
5   second
8   third
9   fourth

SET @user_sort = 9

9   fourth
15  fifth
20  sixth
1   first
5   second
8   third

答案 2 :(得分:1)

ORDER BY(FIELD(位置,1,5,8,9,15,20)+参数)%7

编辑:为了让花生画廊满意,一般的解决方案是:

ORDER BY(SELECT ix + parameter - 1 FROM(SELECT i.position,@ ix = = @ix + 1 AS ix FROM(SELECT @ix:= 0)AS n,items AS i ORDER BY position)AS s WHERE s.position = items.position)%(SELECT COUNT(*)FROM items)

答案 3 :(得分:1)

我在这里正在讨论海滩的解决方案,但是取消了自连接,只选择 items 表两次(并使用Oracle语法):

select 
    i.position
  , i.name
from(
  select 
      items.*
    , ( SELECT COUNT(*) FROM items ) AS maxrows
  from items
  order by position
) i
order by 
  case 
    when rownum > maxrows - 2 -- NOTE: change "2" to your "position" variable
      then 1 - 1 / rownum -- pseudo-rownum < 1, still ascending
    else
      rownum
  end
;

答案 4 :(得分:0)

如果它是一个设置列表,您知道可以执行以下操作的项目数:

SELECT *
FROM Items
ORDER BY CASE WHEN Position >= Position THEN POSITION ELSE Position+1000 END

但它真的很难看。

答案 5 :(得分:0)

这在SQL中做起来并不理想。

我有解决方案,但是对于大型表格,它会很慢。

DECLARE @iOrder INT
SET @iOrder = 4

SELECT abc.position,abc.name FROM
(
SELECT position,name,ROW_NUMBER() OVER (ORDER BY position) AS rownum
FROM items
) abc
WHERE abc.rownum >= @iOrder
UNION ALL
SELECT def.position, def.name FROM
(
SELECT position,name,ROW_NUMBER() OVER (ORDER BY position) AS rownum
FROM items
) def
WHERE def.rownum < @iOrder

请注意,使用UNION(没有全部)会重新排序结果,因为它会查找重复项

答案 6 :(得分:0)

根据John的评论,但改为使用LIMIT语法(ROW_NUMBER / OVER在MySQL中不起作用,除了LIMIT更容易阅读):

(
    SELECT position, name FROM items
    ORDER BY position
    LIMIT @offset, @bignum
) UNION ALL (
    SELECT position, name FROM items
    ORDER BY position
    LIMIT @offset
)

其中@bignum是一个任意数字,高于你可能拥有的任何结果数。

我仍然不完全相信这在实践中会比重新排列网络服务器上的列表更快......我想,这将完全取决于你如何处理结果集以及它有多大。但至少它避免了海滩聪明方法中的自我交叉加入。