2015-06-18 2 views
5

У меня есть столбец BIGINT, в котором я хочу выполнить частичное совпадение.SQL Like/Contains на столбце BIGINT

например. @search = 1 должен возвращать все записи, где первое число равно 1 (1, 11, 100 и т. Д.). В принципе то же самое, что и varchar LIKE.

Я попытался:

DECLARE @search VARCHAR 
SET @search = '1' 

и

SET @search = '1%' 

И использовали:

SELECT 
    id FROM table 
WHERE 
    CAST(id AS varchar) LIKE @search 

Добавление % к @search не помогает. Любые идеи, как это сделать?

EDIT: это переменная. Если я жестко кодирую строку в предложении WHERE, я получаю результаты, которые я ищу.

SELECT id FROM table WHERE CAST(id AS VARCHAR) LIKE '14%' 

Это дает мне все записи с id 14 * (14, 140, 1400 и т.д.).

+1

можете ли вы разместить свой код с добавленным «%»? – Tim3880

+0

Добавлено более подробно. Извинения, должно быть, это было с самого начала. – hsimah

+1

Какие результаты вы получаете, когда вы просто выбираете CAST (id as Varchar) FROM table? –

ответ

6

Попробуйте вместо этого:

DECLARE @search VARCHAR(10) 
SET @search = '1' 

SELECT id FROM table WHERE CAST(id AS VARCHAR(10)) LIKE @search + '%' 

При литье в VARCHAR, вы должны всегда указывать длину. Если вы не определяете длину, SQL-Server назначит ее для вас. Иногда это будет 1 других будет 30. Читайте this для получения дополнительной информации.

+0

Благодарим вас за ответ. Это работает для @search = '1', но когда я использую '@search = '14', я все еще получаю 1, 10, 11 и т. Д. Любые идеи? – hsimah

+1

См. Мое редактирование. Вы должны указать длину в декларации. –

+0

Поскольку я прокомментировал аналогичный ответ, SQL не является моей сильной стороной. Когда я объявляю размер для поискового запроса, он действительно работает. Большое вам спасибо за решение. – hsimah

0

Это может помочь:

like 1% эквивалентно: все, больше или равно 10, если вы сравниваете числовые. Таким образом, вы можете захотеть сделать похож на следующее:

SELECT 
    id FROM table 
WHERE 
    id >= @search*10 [email protected] is of course int 
+0

запрос в OP использует оператор 'LIKE' для сравнения со строкой' '1%' '. Символ '%' - это дикая карта в SQL Server. –

+0

Я знаю, что такое 'like', я старался не использовать' cast' 'int' для' varchar', сравнение было бы очень плохой в производительности. Он не будет использовать никаких «индексов». – ANewGuyInTown

+0

К сожалению. Я думал о чем-то другом, я отредактирую свой пост. – ANewGuyInTown

2

Проблема с вашим @search. Попробуйте, как показано ниже, вместо

create table aaa (id bigint); 
insert into aaa values(1),(11),(100),(111),(1111),(2222); 

Select Query

SELECT 
    id FROM aaa 
WHERE 
    CAST(id AS varchar(1000)) LIKE '1%'; 

(OR), как показано ниже

DECLARE @search VARCHAR; 
SET @search = '1'; 

SELECT 
    id FROM aaa 
WHERE 
    CAST(id AS varchar(1000)) LIKE @search + '%'; 
+0

Благодарим вас за ответ. Это работает для '@search = '1'', но когда я использую' @search =' 14 ', я все еще получаю 1, 10, 11 и т. Д. Любые идеи? – hsimah

+1

это из-за строки 'DECLARE @search VARCHAR;' без какой-либо спецификации размера он всегда принимает первый символ, который в этом случае равен 1. – Rahul

+0

Я вижу. SQL не является моей сильной стороной, поэтому такие виды ошибок всегда меня вылавливают. Когда я объявляю размер, он действительно работает. Огромное спасибо. – hsimah

3

Вместо использования оператора LIKE попробуйте использовать функцию LEFT. Это вернет левую часть символьной строки с указанным количеством символов.

SELECT id 
FROM table 
WHERE LEFT(CAST(id AS varchar), 1) = '1' 

Я не уверен, но я должен предположить, что это будет иметь более высокую производительность, чем при использовании оператора LIKE, тем более, что вы знаете, вы просто хотите, чтобы сравнить с первыми символами. Часто использование функции в предложении WHERE часто приводит к низкой производительности, потому что запрос не может использовать любые индексы, которые могут существовать в столбце. Однако в этом случае запрос вызывает функцию CAST, поэтому преимущество индекса уже потеряно.

Редактировать: Если сравнение должно быть для переменного количества цифр, вы можете использовать функцию LEN для определения количества символов для возвращаемой функции LEFT.

SELECT id 
FROM table 
WHERE LEFT(CAST(id AS varchar),LEN(@search)) = @search 
+0

Спасибо за ответ. Поисковый запрос будет получен с пользовательского ввода, поэтому длина будет такой же, как и строка, которую они подают с лицевой стороны. Я мог бы получить длину строки и использовать ее. Хороший альтернативный ответ. – hsimah

+0

На данный момент мы подталкиваем к этому выпуску, но на следующей неделе я запустим некоторые показатели производительности на этом и принятом ответе. – hsimah

+0

Мне было бы интересно узнать ваши результаты, если у вас есть шанс оценить эффективность двух подходов. Часто использование функции в предложении WHERE часто приводит к низкой производительности, потому что запрос не может использовать любые индексы, которые могут существовать в столбце. Однако в этом случае запрос переводит столбец в varchar, поэтому преимущество индекса уже потеряно. –

3

Не похоже, но должно это сделать. Замените x идентификатором.

WHERE 
(x >= 1000000000000000000 AND x < 2000000000000000000) OR 
(x >= 100000000000000000 AND x < 200000000000000000) OR 
(x >= 10000000000000000 AND x < 20000000000000000) OR 
(x >= 1000000000000000 AND x < 2000000000000000) OR 
(x >= 100000000000000 AND x < 200000000000000) OR 
(x >= 10000000000000 AND x < 20000000000000) OR 
(x >= 1000000000000 AND x < 2000000000000) OR 
(x >= 100000000000 AND x < 200000000000) OR 
(x >= 10000000000 AND x < 20000000000) OR 
(x >= 1000000000 AND x < 2000000000) OR 
(x >= 100000000 AND x < 200000000) OR 
(x >= 10000000 AND x < 20000000) OR 
(x >= 1000000 AND x < 2000000) OR 
(x >= 100000 AND x < 200000) OR 
(x >= 10000 AND x < 20000) OR 
(x >= 1000 AND x < 2000) OR 
(x >= 100 AND x < 200) OR 
(x >= 10 AND x < 20) OR 
(x = 1) 
+0

Я предполагаю, что это будет иметь лучшую производительность, чем решения на основе CAST, поскольку индекс может использоваться (если он существует). Решения 'CAST' должны будут использовать каждую строку BIGINT для оценки предиката. – g2server

1

Существует способ сделать это без преобразования в VARCHAR(30) - но я не проверял, чтобы увидеть, если производительность на самом деле лучше. LOG10() не дешево, но целое разделение есть. Поэтому тестирование оправдано.

Дано:

create table aaa (id bigint); 
insert into aaa values(1),(11),(100),(111),(1111),(2222),(1234),(4531),(1345134),(64513),(6451999123); 

declare @want int = 64 -- and these are your starting digits 

Сумасшедшая математика:

select id 
from dbo.aaa 
WHERE id/(CASE WHEN (LOG10(id) -CEILING(LOG10(@want))) > 1 
    THEN POWER(10 , CEILING(log10(id-1)-CEILING(LOG10(@want)))) 
    ELSE 1 END) = @want; 

В принципе, пара LOG10() определяет количество цифр, сдвиг вправо (с помощью целочисленного деления), так что только требуемое количество цифры остаются.

+0

Ничего себе. Такого рода математика болит голова! Интересное решение, тем не менее, очень романтично. – hsimah

Смежные вопросы