Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/56.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
基于SQL查询的特殊订单_Sql_Mysql_Sql Order By - Fatal编程技术网

基于SQL查询的特殊订单

基于SQL查询的特殊订单,sql,mysql,sql-order-by,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 =

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

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
现在,列表的顺序应该根据用户提供的参数进行更改。此参数指定哪个记录先出现,如下所示:

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


感谢按字段位置排序,1、5、8、9、15、20+参数%7

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


按位置排序选择ix+参数-1从选择i.position,@ix:=@ix+1作为ix从选择@ix:=0作为n,按位置排序的项目作为s,其中s.position=items.position%SELECT COUNT*FROM items

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

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

但是它真的很难看。

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

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


可能使用链表

这在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而不使用all,将对结果进行重新排序,因为它将查找重复的结果

请参见此操作的原理。使用通用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
设置@user\u sort=1

设置@user\u sort=2

设置@user\u sort=9


根据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是一个任意数,高于您可能得到的任何结果数


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

我在这里重复介绍beach的解决方案,但消除了自连接,仅从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
;

您的解决方案是硬编码订单?添加另一条记录时会发生什么情况?我很抱歉,但这是行不通的。我发布了一个针对所问问题的解决方案,而不是针对其他随机问题的解决方案。我最终使用了类似于此的解决方案,但我想指出的是,此解决方案并没有像要求的那样将最后一项放在首位。订单错了,这是一个很好的解决办法。祝贺我得看看它的性能如何。不错,但自连接似乎没有必要;请看我的看法。是的,在SQL中这样做可以减少web服务器上所需的内存量,从而可以处理更多的请求。数据库位于另一台服务器上。在web服务器上拼接列表应该不会太费力。不过,像beach这样的解决方案在数据库服务器上要困难得多,因为它涉及到一个自交叉连接,MySQL将无法优化查询计划。我从未使用过MySQL,所以我不知道该服务器的性能缺陷,也无法测试它。即使使用索引主键,MySQL的性能也会那么差吗?我在MSSQL中多次使用此技巧,没有遇到任何问题。但是,是的,理想情况下,这应该在数据库服务器之外进行。这有点教条,但是用SQL在数据库中实现这一点可以说更好,因为它将与数据相关的业务逻辑与应用程序代码隔离开来。这是一个有趣的问题,我喜欢各种各样的解决方案。我想知道rownum来自何方,我猜你在使用oracle,现在看到你说的了。这就是老版本的MSSQL和MySQL的问题——没有rownum。但是,自连接样式是可移植的,这可能很有用。如果可用,应该应用平台调整。这是rownum的可移植解决方案吗?哎呀!但是,很公平。
(
    SELECT position, name FROM items
    ORDER BY position
    LIMIT @offset, @bignum
) UNION ALL (
    SELECT position, name FROM items
    ORDER BY position
    LIMIT @offset
)
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
;