3

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

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 数据库中的示例都可以。

谢谢

4

7 回答 7

2

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

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

可能使用链表。

于 2009-02-09T23:32:20.100 回答
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”。

结果:

设置@user_sort = 0

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

设置@user_sort = 1

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

设置@user_sort = 2

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

设置@user_sort = 9

9   fourth
15  fifth
20  sixth
1   first
5   second
8   third
于 2009-02-10T00:38:08.820 回答
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)

于 2009-02-09T23:23:48.827 回答
1

我在这里重复海滩的解决方案,但消除了自联接,只从项目表中选择两次(并使用 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
;
于 2009-02-10T22:32:47.107 回答
0

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

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

但它真的很丑。

于 2009-02-09T23:24:26.720 回答
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 (Without the all) 将重新排序结果,因为它会寻找重复项

于 2009-02-10T00:07:45.710 回答
0

根据约翰的评论,但使用 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 是一个任意数字,高于您可能拥有的任意数量的结果。

我仍然不完全相信这实际上会比重新排列 Web 服务器上的列表更快......我想这将完全取决于您如何处理结果集以及它有多大。但至少它避免了海滩巧妙方法中涉及的自交叉连接。

于 2009-02-10T02:40:03.690 回答