2017-02-09 31 views
2

我想生成每隔三行生成行號,每3行

CREATE TABLE #test(period INT) 

INSERT INTO #test 
VALUES  (602),(603),(604),(605),(606),(607),(608),(609) 

我知道我們可以用row_number窗函數或while環或cursor

SELECT period, 
     (Row_number()OVER(ORDER BY period) - 1)/3 + 1 
FROM #test 

結果生成序列號;

+--------+-----+ 
| period | seq | 
+--------+-----+ 
| 602 | 1 | 
| 603 | 1 | 
| 604 | 1 | 
| 605 | 2 | 
| 606 | 2 | 
| 607 | 2 | 
| 608 | 3 | 
| 609 | 3 | 
+--------+-----+ 

是否有任何其他的方式來實現這一目標數學。不會有周期

+0

就我個人而言,有沒有更好的方式來做到這一點。畢竟,這是ROW_NUMBER的設計目的,不是嗎?你爲什麼想要使用另一種方法? – Tyron78

+0

爲什麼你要使用其他方法,如果這工作正常?是否有理由讓它更具數學意義? – Saypontigohe

+0

@Saypontigohe&@ Tyron78 - 原始要求的方式比這更復雜。我在另一個窗口函數的'partition by'中使用這個序列。由於'Row_Number'查詢變得非常緩慢 –

回答

6

的數學或算術方法可以是使用期數字本身:

-- table init here 
DECLARE @MIN_PERIOD INT = (SELECT MIN(period) FROM #test) 

SELECT period, 
     (period - @MIN_PERIOD)/3 + 1 AS seq 
FROM #test 

這隻要「時期之間不存在任何差距」,它仍然是正確的。

如果您需要在主查詢中使用WHERE子句,還可以將其應用於SELECT MIN()查詢。只要WHERE不會導致時期差距,將工作。

+0

不錯的一個... didn'不要把這個弄出來。 – Tyron78

+0

很棒..那很有幫助 –

1

什麼這樣的事情之間沒有任何間隙...

WITH X AS (
SELECT * 
    ,ROW_NUMBER() OVER (ORDER BY [period] ASC) rn 
FROM #test 
) 
SELECT [period] 
     ,ROW_NUMBER() OVER (PARTITION BY (X.rn % 3) ORDER BY rn ASC) rn 
FROM X 
ORDER BY [period] 
+1

謝謝..我不想使用'Row_Number' –

+0

問題是沒有row_number的另一種方法... – Tyron78

2

可以通過NTILE()函數來實現,但我認爲它不如ROW_NUMBER()更有效,主要是因爲此方法必須獲得總計數才能確定組的數量。

創建測試環境:

/* -- SQL 2016 
DROP TABLE IF EXISTS #test; 
GO 
*/ 

IF OBJECT_ID('tempdb.dbo.#test') IS NOT NULL DROP TABLE #test 

CREATE TABLE #test(period INT); 
GO 

INSERT INTO #test -- Make it bigger 
VALUES  (602),(603),(604),(605),(606),(607),(608),(609); 
GO 51 

ROW_NUMBER方法:

SELECT /*ROW_NUM*/ period, 
     (Row_number()OVER(ORDER BY period) - 1)/3 + 1 
FROM #test; 
GO 

ROW_NUMBER

IO和時間演出: 縮短可讀性

(400行受影響)表'工作臺'。掃描計數0,邏輯讀取 0,物理讀取0 '#test_00000000000E'。掃描計數1,邏輯讀取1次,物理讀0

(1影響行(S))

SQL Server的執行時間:CPU時間= 0毫秒,經過的時間= 85 毫秒。

NTILE方法

DECLARE @ntile_var int; 

SELECT @ntile_var = COUNT(*) FROM #test; 

SELECT /*NTILE*/period 
    , NTILE(@ntile_var/3) OVER (ORDER BY period) 
FROM #test 

IO和時間演出: 縮短可讀性

SQL Server分析和編譯時間:CPU時間= 0毫秒,經過的時間= 0毫秒。

SQL Server執行時間:CPU時間= 0毫秒,已用時間= 0毫秒。

SQL Server解析和編譯時間:CPU時間= 0毫秒,耗用時間= 0毫秒。

表 '#test__00000000000E'。掃描計數1,邏輯讀取1次,物理讀0

(1影響行(S))

SQL Server的執行時間:CPU時間= 0毫秒,經過時間= 0毫秒。

(400行受影響)表'工作臺'。掃描計數3,邏輯讀取 811,物理讀取0 表 '#test ___ 00000000000E'。掃描計數1,邏輯讀取1,物理讀取0

(1行(一個或多個)受影響)

SQL Server的執行時間:CPU時間= 0毫秒,經過時間= 93

NTILE

這兩個產生相同的結果:

Results_GroupsOf3

但是有一個警告! MSDN把它充分地作爲(強調)

如果行分區中的數量不通過 integer_expression整除,這將導致由 一個構件不同兩種尺寸的基團。較大的組以OVER子句指定的訂單 之前的較小組進行。例如,如果行的總數爲 爲53且組數爲5,則前三組 將有11行,剩下的兩組每行將有10行。

於是用NTILE方法,你可以得到的4幾組,讓他們的休息可以是3