SQL для возврата таблицы на основе ввода строки - PullRequest
1 голос
/ 02 июня 2010

Я новичок в T-SQL. Поэтому, пожалуйста, помогите мне написать sql.

У меня есть таблица Price (Столбец кода является первичным столбцом):

Code    Value
A1       234
A2       525 
A3       566

Я введу строку, и sql нужно вернуть таблицу.

Ex1: вход «A2» -> return:

Code    Value
A2       525

Ex2: вход «A1 A3» -> return:

Code    Value
A1       234
A3       566

Пример 3: вход «А1 А3 А1» -> возврат:

Code    Value
A1       234
A3       566

Пример 4: вход «А1 А4» -> возврат:

Code    Value
A1       234

Пожалуйста, помогите мне. Я использую SQL Server 2005. Tks.

Ответы [ 2 ]

2 голосов
/ 02 июня 2010
SELECT [Price].Code, [Price].Value FROM [Price] WHERE [Price].Code IN ('A1', 'A2');

Это очень эффективно, но имеет два ограничения:

  • Нельзя использовать обычные параметры SQL в предложении IN, поэтому вам придется автоматически добавлять их в строку SQL, что в некоторых случаях может открыть SQL-инъекции.

  • Это не совсем введенный вами формат ввода: вместо A2 A2 это 'A1', 'A2'.

В любом случае, удачи!

РЕДАКТИРОВАТЬ: Если вы действительно хотите использовать формат A1 A2, вы не можете использовать IN и вам придется разделить строку, а затем проверить, содержит ли она текущий [Price].Code. Просто отметьте, что это будет гораздо менее эффективно, чем мой первый пример.

T-SQL по умолчанию не поддерживает Split, поэтому вам придется добавить его вручную:

CREATE FUNCTION [dbo].[Split]
(    
    @RowData NVARCHAR(MAX),
    @Delimeter NVARCHAR(MAX)
)
RETURNS @RtnValue TABLE 
(
    ID INT IDENTITY(1,1),
    Data NVARCHAR(MAX)
) 
AS
BEGIN 
    DECLARE @Iterator INT
    SET @Iterator = 1

    DECLARE @FoundIndex INT
    SET @FoundIndex = CHARINDEX(@Delimeter,@RowData)

    WHILE (@FoundIndex>0)
    BEGIN
        INSERT INTO @RtnValue (data)
        SELECT 
            Data = LTRIM(RTRIM(SUBSTRING(@RowData, 1, @FoundIndex - 1)))

        SET @RowData = SUBSTRING(@RowData,
                @FoundIndex + DATALENGTH(@Delimeter) / 2,
                LEN(@RowData))

        SET @Iterator = @Iterator + 1
        SET @FoundIndex = CHARINDEX(@Delimeter, @RowData)
    END

    INSERT INTO @RtnValue (Data)
    SELECT Data = LTRIM(RTRIM(@RowData))

    RETURN
END

А потом, вы могли бы сделать что-то вроде этого:

SELECT [Price].Code, [Price].Value FROM [Price] 
JOIN Split(@Codes, ' ') AS [Code] 
 ON [Code].Data = [Price].Code

Вот источник для функции Split .

0 голосов
/ 02 июня 2010

Как уже упоминал Алон, вам нужна функция или запрос, чтобы разбить значения на строки в таблице. Другой способ сделать это - с помощью таблицы Numbers, которая может быть статической или созданной как часть общего выражения таблицы:

Declare @Alist varchar(50);
Declare @Delimiter char(1);
Declare @DelimiterLength int;

Set @Delimiter = ' ';
Set @DelimiterLength = DataLength(@Delimiter);
Set @Alist = 'A1 A2 A3';
Set @Alist = @Delimiter + @Alist + @Delimiter;

With Numbers As
    (
    Select Row_Number() Over ( Order By C1.object_id ) As Value
    From sys.columns As C1
        Cross Join sys.columns As C2
    )
Select CharIndex(@Delimiter, @Alist, N.Value) + @DelimiterLength As Position            
    , Substring (
                @Alist
                , CharIndex(@Delimiter, @Alist, N.Value) + @DelimiterLength         
                , CharIndex(@Delimiter, @Alist, N.Value + 1)                            
                    - ( CharIndex(@Delimiter, @Alist, N.Value) + @DelimiterLength ) 
                ) As Value
From Numbers As N
Where N.Value Between 1 And ( Len(@Alist) - 1 )
    And Substring(@Alist, N.Value, @DelimiterLength) = @Delimiter
Order By N.Value

Здесь разделитель пространства представляет небольшую проблему. Функция Len игнорирует пробелы при определении, поэтому я использовал функцию DataLength, а также гарантировал, что @Delimiter был объявлен как varchar вместо nvarchar. DataLength вернет количество байтов в строке, которое будет вдвое больше общего количества символов для nvarchar.

Числа CTE (или это может быть статическая таблица) - это просто статический список последовательных целых чисел, который весьма полезен для ситуаций, подобных этой.

Подход такого типа также может быть включен в общий запрос, где вы анализируете каждую строку в другой таблице, например:

With Numbers As
    (
    Select Row_Number() Over ( Order By C1.object_id ) As Value
    From sys.columns As C1
        Cross Join sys.columns As C2
    )
Select CharIndex(@Delimiter, A.List, N.Value) + @DelimiterLength            
    , Substring (
                A.List
                , CharIndex(@Delimiter, A.List, N.Value) + @DelimiterLength         
                , CharIndex(@Delimiter, A.List, N.Value + 1)                            
                    - ( CharIndex(@Delimiter, A.List, N.Value) + @DelimiterLength ) 
                )
From Numbers As N
    Cross Join ( Select A1.List From SomeTable ) As A
Where N.Value Between 1 And ( Len(A.List) - 1 )
    And Substring(A.List, N.Value, @DelimiterLength) = @Delimiter
Order By N.Value
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...