Вопрос по sql, sql-server – Как использовать список значений через запятую в качестве фильтра в T-SQL?
У меня есть простой SQL-запрос, начинающийся с:
<code>SELECT top 20 application_id, [name], location_id FROM apps </code>
Теперь я хотел бы закончить, чтобы он сделал это (написано в псевдокоде)
<code>if @lid > 0 then WHERE location_id IN (@lid) else WHERE location_id is all values in location_id column </code>
По запросу, вот пример
<code>application_id name location_id ---------------------------------------------------------- 1 Joe Blogs 33 2 Sam Smith 234 3 Jeremy Carr 33 </code>
@ locid - это результаты, предоставленные пользователем, например, '33, 234 '
If @lid пуст, тогда я бы хотел вывести все строки для location_id с именами и application_id. В противном случае я хотел бы, чтобы он выводил все строки относительно предоставленных чисел в @lid (обозначая location_id.
Так что, если @lid равен 0:
<code>application_id name location_id ---------------------------------------------------------- 1 Joe Blogs 33 2 Sam Smith 234 3 Jeremy Carr 33 </code>
В противном случае, если @lid содержит '33'
<code>application_id name location_id ---------------------------------------------------------- 1 Joe Blogs 33 3 Jeremy Carr 33 </code>
Случа, который служит цели IIF или троичного оператора. Пожалуйста, проверьте эту ссылкуhttp: //msdn.microsoft.com/en-us/library/ms181765.asp
Возгласы
@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
)
например, «33, 234» и т. Д., Тогда никакое решение здесь не будет работать. Тем не менее, я думаю, что они были опубликованы до вашего обновления с этой информацией.
Я полагаю, потому что ты это сказал:
@ locid - это результаты, предоставленные пользователем, например, '33, 234 '
Вы не можете развернуть переменную напрямую, чтобыlocation_in IN (33, 234)
. Вы на самом деле проситеlocation_id = '33, 234'
, которая завершится неудачно с преобразованием CAST из-за приоритета типа данных.
Сначала нужно разобрать список в табличную форму для использования в конструкции JOIN / EXISTS. Есть несколько вариантов, и Эрланд описывает их все здесь: Массивы и списки в SQL Server 2005
IN со списком через запятую: SQL Server
Если ваш@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
конструирует.
WHERE CHARINDEX(LocationId, @lid) > 1
DECLARE @lid SMALLINT
SET @lid = 0
ВЫБЕРИТЕ топ-20 application_id, [name], location_id
Приложения от
ГДЕ ((@lid> 0 И location_id = @lid)
OR (@lid = 0 AND location_id > @lid))
If @lid = 0, тогда он вернет ВСЕ строки. IF @lid имеет конкретное значение, возвращается только строка для этого значения @lid.
убрать пробелы и вставить значения во временную таблицу. Затем вы можете присоединить свой запрос к временной таблице.
Это фрагмент кода 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
с (о троичном операторе, но, как вы можете видеть, для этого вам не нужно ничего похожего на троичный оператор):
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