Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/ant/2.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_Sql Server_Database_Sorting - Fatal编程技术网

Sql 基于旋转排序数据

Sql 基于旋转排序数据,sql,sql-server,database,sorting,Sql,Sql Server,Database,Sorting,假设我有一个数据集: 我下一个订单 1456 1679 1 1679 1679 2 1578 1679 3 9492 1679 4 此数据集中唯一更改的列是NEXT。ID始终是唯一的,下一个始终与单个ID相关,并将在每一行中重复。顺序是一个顺序整数 我需要一个orderby或其他SQL语句来执行以下排序: 下一个ID始终位于订单的底部 在NEXT的顺序之后具有顺序更高顺序的ID始终位于顶部 然后按顺序进行排序,从第二行到第一行的顺序是在第一行的顺序之后的下一行 例如: 对于上

假设我有一个数据集: 我下一个订单 1456 1679 1 1679 1679 2 1578 1679 3 9492 1679 4

此数据集中唯一更改的列是NEXT。ID始终是唯一的,下一个始终与单个ID相关,并将在每一行中重复。顺序是一个顺序整数

我需要一个orderby或其他SQL语句来执行以下排序:

下一个ID始终位于订单的底部

在NEXT的顺序之后具有顺序更高顺序的ID始终位于顶部

然后按顺序进行排序,从第二行到第一行的顺序是在第一行的顺序之后的下一行

例如:

对于上表,订购将为 1578 9492 1456 1679年

next已更改的另一个表:

我下一个订单 1456 1578 1 1679 1578 2 1578 1578 3 9492 1578 4

将是:

9492 1456 1679 1578

Fiddle使用Postgresql,因为Sql Server目前似乎已经崩溃

Fiddle使用Postgresql,因为Sql Server目前似乎已崩溃。

这应该可以:

样本数据:

IF OBJECT_ID('tempdb..#temp') IS NOT NULL
    DROP TABLE #temp;

CREATE TABLE #temp(ID      INT
              , [NEXT]  INT
              , [ORDER] INT);

INSERT INTO #temp
VALUES
      (1456
     , 1679
     , 1),
      (1679
     , 1679
     , 2),
      (1578
     , 1679
     , 3),
      (9492
     , 1679
     , 4);
查询:

DECLARE @rowcount INT;

SELECT @rowcount = COUNT(1)
FROM   #temp
WHERE  [ORDER] >
              (SELECT [ORDER]
               FROM   #temp
               WHERE  ID = [NEXT]);

SELECT ID
FROM
         (SELECT *
              , rn = ROW_NUMBER() OVER(ORDER BY [ORDER])
          FROM   #temp
          WHERE  [ORDER] >
                        (SELECT [ORDER]
                        FROM   #temp
                        WHERE  ID = [NEXT])
                        UNION
                        SELECT *
                            , rn = @rowcount + ROW_NUMBER() OVER(ORDER BY [ORDER])
                        FROM   #temp
                        WHERE  [ORDER] <=
                                      (SELECT [ORDER]
                                       FROM   #temp
                                       WHERE  ID = [NEXT])) AS A
ORDER BY rn;
结果:

这应该起作用:

样本数据:

IF OBJECT_ID('tempdb..#temp') IS NOT NULL
    DROP TABLE #temp;

CREATE TABLE #temp(ID      INT
              , [NEXT]  INT
              , [ORDER] INT);

INSERT INTO #temp
VALUES
      (1456
     , 1679
     , 1),
      (1679
     , 1679
     , 2),
      (1578
     , 1679
     , 3),
      (9492
     , 1679
     , 4);
查询:

DECLARE @rowcount INT;

SELECT @rowcount = COUNT(1)
FROM   #temp
WHERE  [ORDER] >
              (SELECT [ORDER]
               FROM   #temp
               WHERE  ID = [NEXT]);

SELECT ID
FROM
         (SELECT *
              , rn = ROW_NUMBER() OVER(ORDER BY [ORDER])
          FROM   #temp
          WHERE  [ORDER] >
                        (SELECT [ORDER]
                        FROM   #temp
                        WHERE  ID = [NEXT])
                        UNION
                        SELECT *
                            , rn = @rowcount + ROW_NUMBER() OVER(ORDER BY [ORDER])
                        FROM   #temp
                        WHERE  [ORDER] <=
                                      (SELECT [ORDER]
                                       FROM   #temp
                                       WHERE  ID = [NEXT])) AS A
ORDER BY rn;
结果:


与Joel的答案类似,仅使用窗口函数而不是内部联接或交叉应用:

SELECT
    *
FROM
    #temp t
ORDER BY
    CASE
       WHEN t.[Order] > MAX(CASE WHEN ID = [NEXT] THEN [ORDER] END) OVER () THEN -999999999 + t.[Order]
       ELSE t.[Order]
    END
这是一个使用交叉应用的版本

SELECT
    t.*
FROM
    #temp t
    CROSS APPLY (SELECT [Order] FROM #temp WHERE ID = NEXT) n
ORDER BY
    CASE
       WHEN t.[Order] > n.[Order] THEN -99999999 + t.[Order]
       ELSE t.[Order]
    END

与Joel的答案类似,仅使用窗口函数而不是内部联接或交叉应用:

SELECT
    *
FROM
    #temp t
ORDER BY
    CASE
       WHEN t.[Order] > MAX(CASE WHEN ID = [NEXT] THEN [ORDER] END) OVER () THEN -999999999 + t.[Order]
       ELSE t.[Order]
    END
这是一个使用交叉应用的版本

SELECT
    t.*
FROM
    #temp t
    CROSS APPLY (SELECT [Order] FROM #temp WHERE ID = NEXT) n
ORDER BY
    CASE
       WHEN t.[Order] > n.[Order] THEN -99999999 + t.[Order]
       ELSE t.[Order]
    END

另外,请标记您正在使用的相关数据库,如SQLServer、oracle、mysql、postgres。如果下一个是最高顺序,例如9492,该怎么办?按表中的顺序返回订单?@Matt没错!另外,请标记您正在使用的相关数据库,如SQLServer、oracle、mysql、postgres。如果下一个是最高顺序,例如9492,该怎么办?按表中的顺序返回订单?@Matt没错!我喜欢APPLY,但是由于内部查询的结果对于每一行都应该是一致的,因此我认为在这种情况下,内部连接是更好的选择。不过,加上一个窗口功能。这可能是最好的总体选择。它可能更快,并且您包含了将结果完全按ORDER BY子句排序的代码。@JoelCoehoorn我不确定我是否明白为什么您觉得交叉应用不会在每个实例中产生与您相同的结果?本例中的交叉应用程序基本上与内部连接完全相同,因为您是在1=1上连接的,并且我没有将任何值从表传递到应用程序中,因此它完全包含在order by中,就像您的一样。最上面的一个是带有条件聚合的窗口函数,因此不需要使用该函数进行apply或inner连接。是的,它将返回相同的结果。我对查询优化器识别apply运算符中的语句没有使用外部查询中的任何数据的能力缺乏信心,尽管我承认我实际上没有看过执行计划。@JoelCoehoorn是的,我也没有看过,我想看看。我会特别好奇window函数的执行计划与其他函数的执行计划,也许我会在我喜欢应用的某个点上进行检查,但是由于内部查询的结果对于每一行都应该是一致的,我认为在这种情况下,内部连接是更好的选择。不过,加上一个窗口功能。这可能是最好的总体选择。它可能更快,并且您包含了将结果完全按ORDER BY子句排序的代码。@JoelCoehoorn我不确定我是否明白为什么您觉得交叉应用不会在每个实例中产生与您相同的结果?本例中的交叉应用程序基本上与内部连接完全相同,因为您是在1=1上连接的,并且我没有将任何值从表传递到应用程序中,因此它完全包含在order by中,就像您的一样。最上面的一个是带有条件聚合的窗口函数,因此不需要使用该函数进行apply或inner连接。是的,它将返回相同的结果。我对查询优化器识别apply运算符中的语句没有使用外部查询中的任何数据的能力缺乏信心,尽管我承认我实际上没有看过执行计划。@JoelCoehoorn是的,我也没有看过,我想看看。我会特别好奇窗口函数的执行计划与其他函数的执行计划,也许我会在某个时候抽空检查一下