1

Я бы хотел, чтобы динамическое число пар первого/конечного времени передавалось функции в качестве входного параметра. Затем функция будет использовать список вместо одного старта и одного конечного времени в select select.Функция Microsoft SQL Server 2005, передающая список начальных и конечных времен

CREATE FUNCTION [dbo].[GetData] 
(
    @StartTime datetime, 
    @EndTime datetime 
) 
RETURNS int 
AS 
BEGIN 
    SELECT @EndTime = CASE WHEN @EndTime > CURRENT_TIMESTAMP THEN CURRENT_TIMESTAMP ELSE @EndTime END 

    DECLARE @TempStates TABLE 
     (StartTime datetime NOT NULL 
     , EndTime datetime NOT NULL 
     , StateIdentity int NOT NULL 
     ) 

    INSERT INTO @TempStates 
    SELECT StartTime 
     , EndTime 
     , StateIdentity 
    FROM State 
    WHERE StartTime <= @EndTime AND EndTime >= @StartTime 

    RETURN 0 
END 
+0

В чем вопрос? – RedFilter

ответ

1

Вам нужен способ разделить и обработать строку в TSQL, есть много способов сделать это. Эта статья охватывает плюсы и минусы почти каждый метод:

"Arrays and Lists in SQL Server 2005 and Beyond, When Table Value Parameters Do Not Cut it" by Erland Sommarskog

нужно создать раздельную функцию. Это как функция разделения может быть использовано:

SELECT 
    * 
    FROM YourTable        y 
    INNER JOIN dbo.yourSplitFunction(@Parameter) s ON y.ID=s.Value 

I prefer the number table approach to split a string in TSQL но есть множество способов, чтобы разделить строки в SQL Server, см предыдущей ссылки, объясняющие плюсы и минусы каждого из них.

Для метода Числа таблицы для работы, вы должны сделать это один раз настройки таблицы, которая будет создавать таблицу Numbers, которая содержит строки от 1 до 10000:

SELECT TOP 10000 IDENTITY(int,1,1) AS Number 
    INTO Numbers 
    FROM sys.objects s1 
    CROSS JOIN sys.objects s2 
ALTER TABLE Numbers ADD CONSTRAINT PK_Numbers PRIMARY KEY CLUSTERED (Number) 

После того как таблица Numbers устанавливается , создать разбитую функцию:

CREATE FUNCTION [dbo].[FN_ListToTableRows] 
(
    @SplitOn char(1)  --REQUIRED, the character to split the @List string on 
    ,@List  varchar(8000)--REQUIRED, the list to split apart 
) 
RETURNS TABLE 
AS 
RETURN 
(
    ---------------- 
    --SINGLE QUERY-- --this will return empty rows, and row numbers 
    ---------------- 
    SELECT 
     ROW_NUMBER() OVER(ORDER BY number) AS RowNumber 
      ,LTRIM(RTRIM(SUBSTRING(ListValue, number+1, CHARINDEX(@SplitOn, ListValue, number+1)-number - 1))) AS ListValue 
     FROM (
       SELECT @SplitOn + @List + @SplitOn AS ListValue 
      ) AS InnerQuery 
      INNER JOIN Numbers n ON n.Number < LEN(InnerQuery.ListValue) 
     WHERE SUBSTRING(ListValue, number, 1) = @SplitOn 
); 
GO 

тест из расщепления:

SELECT 
    RowNumber, CONVERT(datetime,ListValue) AS ListValue 
    FROM dbo.FN_ListToTableRows(',','1/1/2010 12:45am,,2/2/2010 1:23pm,3/3/2010 12:45') 

ВЫВОД:

RowNumber   ListValue 
-------------------- ----------------------- 
1     2010-01-01 00:45:00.000 
2     1900-01-01 00:00:00.000 
3     2010-02-02 13:23:00.000 
4     2010-03-03 12:45:00.000 

(4 row(s) affected) 

отмечают, что отсутствующее значение во входной строке:

'1/1/2010 12:45am,,2/2/2010 1:23pm,3/3/2010 12:45' 
       ^^ 

создано пустое значение строки в наборе результатов функция, которая Преобразовать изменилась до 1900-01-01 00: 00: 00.000, вы можете использовать оператор CASE для обработки их другим способом.

затем создайте свою функцию. Это основано на коде в вопросе. Я не уверен, что он делает, потому что он возвращает int, который всегда равен нулю и ничего не делает с запросом. Но это из функции OPs, поэтому это должна быть простая форма того, что они делают:

CREATE FUNCTION [dbo].[GetData] 
(
    @StartTime varchar(8000), --CSV string of dates: '1/1/2010 12:45am,,2/2/2010 1:23pm,3/3/2010 12:45' 
    @EndTime varchar(8000)  --CSV string of dates: '1/1/2010 12:45am,,2/2/2010 1:23pm,3/3/2010 12:45' 
) 
RETURNS int 
AS 
BEGIN 
    DECLARE @TempStates TABLE 
     (StartTime datetime NOT NULL 
     , EndTime datetime NOT NULL 
     , StateIdentity int NOT NULL 
     ) 

    INSERT INTO @TempStates 
    SELECT s.StartTime 
     , s.EndTime 
     , s.StateIdentity 
    FROM State s 
     CROSS JOIN (SELECT 
         a1.RowNumber 
          ,CONVERT(datetime,a1.ListValue) AS StartTime 
          ,CASE 
           WHEN a2.ListValue > GETDATE() THEN GETDATE() 
           ELSE CONVERT(datetime,a2.ListValue) 
          END AS EndTime 
         FROM dbo.FN_ListToTableRows(',',@StartTime)   a1 
          INNER JOIN dbo.FN_ListToTableRows(',',@EndTime) a2 ON a1.RowNumber=a2.RowNumber 
        ) dt 
    WHERE s.StartTime <= dt.EndTime AND s.EndTime >= dt.StartTime 
    RETURN 0 
END 
GO 
0

То, как я, вероятно, сделаю это, использует OpenXML. Я написал a blog article об этом, если вы хотите увидеть представление о том, как это работает.