Как использовать список значений через запятую в качестве фильтра в T-SQL? - PullRequest
6 голосов
/ 23 июня 2009

У меня есть базовый запрос SQL, начиная с:

SELECT top 20 application_id, [name], location_id FROM apps

Теперь я хотел бы закончить это так, чтобы это делалось (написано в псевдокоде)

if @lid > 0 then
    WHERE location_id IN (@lid)
else
    WHERE location_id is all values in location_id column

По запросу, вот пример

application_id             name               location_id
----------------------------------------------------------
1                          Joe Blogs          33
2                          Sam Smith          234
3                          Jeremy Carr        33

@ locid - это результаты, предоставленные пользователем, например, '33, 234 '

Если @lid пуст, то я бы хотел, чтобы он вывел все строки для location_id с именами и application_id. В противном случае я хотел бы, чтобы он выводил все строки относительно предоставленных чисел в @lid (обозначая location_id.

Итак, если @lid равен 0:

application_id             name               location_id
----------------------------------------------------------
1                          Joe Blogs          33
2                          Sam Smith          234
3                          Jeremy Carr        33

В противном случае, если @lid содержит '33'

application_id             name               location_id
----------------------------------------------------------
1                          Joe Blogs          33
3                          Jeremy Carr        33

Ответы [ 10 ]

3 голосов
/ 23 июня 2009

Если @locid является списком, например, «33, 234» и т. Д., Тогда никакое решение не будет работать. Тем не менее, я думаю, что они были опубликованы до вашего обновления с этой информацией.

Я полагаю, потому что вы сказали это:

@ locid - это результаты, полученные пользователь, например '33, 234 '

Вы не можете развернуть переменную напрямую, чтобы location_in IN (33, 234). На самом деле вы запрашиваете location_id = '33, 234', что не получится при преобразовании CAST из-за приоритета типа данных.

Вы должны сначала проанализировать список в табличной форме для использования в конструкции JOIN / EXISTS. Есть несколько вариантов, и Эрланд описывает их все здесь: Массивы и списки в SQL Server 2005

3 голосов
/ 15 апреля 2011

Предполагая, что @locid & @lid - это одинаковые , я собираюсь использовать @locid ... Следующее будет работать Я разделил его, чтобы он выглядел хорошо на SO.

SELECT application_id, [name], location_id 
FROM apps
WHERE
  ( 
    @locid = 0
    OR 
    CHARINDEX
    ( 
      ',' + CAST(location_id AS VARCHAR(50)) + ','
      , 
      ',' + @locid + ','
      , 
      0 
    ) > 0
  )
3 голосов
/ 23 июня 2009

Попробуйте использовать Case , который служит для IIF или троичного оператора. Пожалуйста, проверьте эту ссылку http://msdn.microsoft.com/en-us/library/ms181765.aspx

ура

2 голосов
/ 06 октября 2011
WHERE CHARINDEX(LocationId, @lid) > 1
2 голосов
/ 23 июня 2009

Смотрите эту запись в моем блоге:

Если ваш @lid представляет собой список целых чисел через запятую, используйте это:

WITH    cd AS
        (
        SELECT  1 AS first, CHARINDEX(',', @lid, 1) AS next
        UNION ALL
        SELECT  next + 1, CHARINDEX(',', @lid, next + 1)
        FROM    cd
        WHERE   next > 0
        ),
        lid AS
        (
        SELECT  CAST(SUBSTRING(@lid, first, CASE next WHEN 0 THEN LEN(@lid) + 1 ELSE next END - first)AS INT) AS id
        FROM    cd
        )
SELECT  d.*
FROM    (
        SELECT  DISTINCT id
        FROM    lid
        ) l
JOIN    apps a
ON      a.location_id = l.id
        AND @lid <> '0'
UNION ALL
SELECT  *
FROM    apps a
WHERE   @lid = '0'

Это намного эффективнее, чем использование OR конструкций.

1 голос
/ 24 июня 2009

Один из способов - разделить строку на запятые, убрать пробелы и вставить значения во временную таблицу. Затем вы можете присоединить свой запрос к временной таблице.

Это фрагмент кода T-SQL, который разбивает список через запятую и вставляет элементы во временную таблицу. Заполнив таблицу, вы можете присоединиться к ней.

-- This bit splits up a comma separated list of key columns
-- and inserts them in order into a table. 
--
if object_id ('tempdb..#KeyCols') is not null
    drop table #KeyCols

create table #KeyCols (
      ,KeyCol           nvarchar (100)
)

set @comma_pos = 0
set @len = len(@KeyCols)
while @len > 0 begin
    set @comma_pos = charindex(',', @KeyCols)
    if @comma_pos = 0 begin
        set @KeyCol = @KeyCols
        set @KeyCols = ''
    end else begin
        set @KeyCol = left (@KeyCols, @comma_pos - 1)
        set @KeyCols = substring(@KeyCols, 
                                 @comma_pos + 1, 
                                 len (@KeyCols) - @comma_pos)
    end
    insert #KeyCols (KeyCol)
    values (@KeyCol)
    set @len = len (@KeyCols)
end
0 голосов
/ 23 июня 2009

Хотя использование 1 = 1 не совсем хорошая практика, здесь все получается.

SELECT top 20 application_id, [name], location_id FROM apps
WHERE
  (@lid > 0 and @lid = location_id)
or
  (isnull(@lid, 0) <= 0 and 1=1)
0 голосов
/ 23 июня 2009

Следующие действия помогут вам.

ОБЪЯВИТЬ @lid SMALLINT

SET @lid = 0

ВЫБЕРИТЕ топ 20 application_id, [name], location_id

ИЗ приложений

ГДЕ ((@lid> 0 И location_id = @lid)

  OR (@lid = 0 AND location_id > @lid))

Если @lid = 0, он вернет ВСЕ строки. Если @lid имеет конкретное значение, возвращается только строка для этого значения @lid.

0 голосов
/ 23 июня 2009

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

SELECT top 20 application_id, [name], location_id 
FROM apps
WHERE @lid = 0 OR location_id IN (@lid)

Но это было до того, как мы узнали, что @lid является varchar и может содержать разные значения, разделенные запятыми.

Ну, это (о CSV) еще один вопрос, который был задан здесь ранее:

Передача списка «in» с помощью хранимой процедуры
Хранимая процедура T-SQL, которая принимает несколько значений Id

0 голосов
/ 23 июня 2009

Вам не нужен троичный оператор для этого:

SELECT top 20 application_id, [name], location_id
FROM apps
WHERE (@lid > 0 AND location_id IN (@lid)) OR @lid <= 0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...