簡體   English   中英

SQL查詢的特殊順序

[英]Special order by on SQL query

我需要顯示由某個數字列排序的數據庫表中的記錄列表。 該表如下所示:

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數據庫中的示例都可以。

謝謝

您確定要在SQL中執行此操作嗎?

對我來說,這聽起來應該將結果加載到某種數據集中,然后根據需要重新排序,或者將起點定位在正確的位置。

可能使用鏈表。

看看這對你有什么用。 使用通用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

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 ORDER BY position)AS s WHERE s。 position = items.position)%(SELECT COUNT(*)FROM items)

我在這里對海灘的解決方案不屑一顧,但是消除了自連接,只從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
;

如果它是一個設置列表,您知道可以執行以下操作的項目數:

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

但它真的很難看。

這真的不是在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(沒有全部)將重新排序結果,因為它將查找重復項

根據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是一個任意數字,高於你可能擁有的任何數量的結果。

我仍然不完全相信這在實踐中會比重新安排網絡服務器上的列表更快...這將完全取決於你如何處理結果集以及它有多大,我想。 但至少它避免了海灘聰明方法中涉及的自我交叉加入。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM