說你有下面的SQL表:建立更多的返回平分高效的MS SQL功能範圍
-- create temp table
CREATE TABLE [tempNums]
(
id INT NOT NULL,
somedate datetime NULL
)
GO
隨着一些數據(參見下面的tempSplitStringToInts定義):
-- with date
INSERT INTO [tempNums]
SELECT id, GETUTCDATE()
FROM [tempSplitStringToInts] ('1,2,3,5,10,100,101,102,103,233,1001,5002,5003,5005,5007,5010',',')
GO
-- without date
INSERT INTO [tempNums]
SELECT id, NULL
FROM [tempSplitStringToInts] ('6,7,8,150,151,152,153,433,2001,2002,2003,2005,3007,10010',',')
GO
怎麼辦你建立更快/更快的功能,將採取一定範圍的數量和一個 標誌位作爲輸入並返回一個範圍值表?
事情是這樣的工作,例如,但是慢了非常大的表:
-- create range function
CREATE FUNCTION [tempFnGetIdRanges]
(
@apps INT,
@has_date BIT
)
RETURNS @ret TABLE
(
RangeNum INT,
MinNum INT,
MaxNum INT
)
AS
BEGIN
DECLARE @i INT = 0;
DECLARE @count INT;
DECLARE @min INT;
DECLARE @max INT = 0;
IF @has_date = 1
BEGIN
SELECT @count = COUNT(id)
FROM [tempNums]
WHERE somedate IS NOT NULL
END
ELSE
BEGIN
SELECT @count = COUNT(id)
FROM [tempNums]
WHERE somedate IS NULL
END
DECLARE @top INT = @count/@apps;
WHILE @i<@apps
BEGIN
IF @[email protected]
BEGIN
-- on last get reminder
SET @top = @top + @apps
END
IF @has_date = 1
BEGIN
SELECT @min = MIN(id), @max = MAX(id)
FROM
(
SELECT TOP (@top) id
FROM [tempNums]
WHERE somedate IS NOT NULL
AND id > @max
ORDER BY id
) XX
END
ELSE
BEGIN
SELECT @min = MIN(id), @max = MAX(id)
FROM
(
SELECT TOP (@top) id
FROM [tempNums]
WHERE somedate IS NULL
AND id > @max
ORDER BY id
) XX
END
INSERT INTO @ret VALUES(@i, @min, @max)
SET @i = @i + 1;
CONTINUE
END
RETURN
END
GO
所以,當您運行以下:
SELECT * FROM [tempFnGetIdRanges](4, 0)
SELECT * FROM [tempFnGetIdRanges](4, 1)
結果的第一條語句:
RangeNum MinNum MaxNum
0 6 8
1 150 152
2 153 2001
3 2002 10010
第二個陳述的結果:
RangeNum MinNum MaxNum
0 1 5
1 10 102
2 103 5002
3 5003 5010
分割功能(供參考,但不是這個問題的要點):
-- create split string function
CREATE FUNCTION [tempSplitStringToInts] (@SourceString VARCHAR(MAX) , @delimeter VARCHAR(10))
RETURNS @IntList TABLE
(
id INT
)
AS
BEGIN
IF RIGHT(@SourceString, LEN(@delimeter))<> @delimeter
BEGIN
SELECT @SourceString = @SourceString + @delimeter
END
DECLARE @LocalStr VARCHAR(MAX)
DECLARE @start INT
DECLARE @end INT
SELECT @start = 1
SELECT @end = CHARINDEX (@delimeter , @SourceString , @start)
WHILE @end > 0
BEGIN
SELECT @LocalStr = SUBSTRING (@SourceString , @start , @end - @start)
IF LTRIM(RTRIM(@LocalStr)) <> ''
BEGIN
INSERT @IntList (id) VALUES (CAST(@LocalStr AS INT))
END
SELECT @start = @end + LEN(@delimeter)
SELECT @end = CHARINDEX (@delimeter , @SourceString , @start)
END
RETURN
END
GO
正如我所說的這個工程,但它是非常大的錶慢。有沒有 更好的方法來編寫
tempFnGetIdRanges
函數?某些原生的SQL可以使用 SQL?如果相關,我正在使用MS SQL 2012
。
這裏有一些確定的性能挑戰。首先,您正在創建表值函數,但它們是多語句表值函數,幾乎總是比標量函數更慢。對於表值函數的性能好處,必須是一個單獨的select語句,僅此而已。我會開始搗毀你的分離器。這是最糟糕的最糟糕的。它在表值函數中有一個循環。這是一些更好的選擇。 http://sqlperformance.com/2012/07/t-sql-queries/split-strings –
非常感謝您的評論。我會看看更好的分離器功能。 – CrnaStena
主要功能是幹什麼的?當HasDate = 1時,它只是將它們分成組,但是當它爲空時,輸出對我來說沒有任何意義。那裏的邏輯是什麼? –