Фильтр SQL нумерует числа от x до x и игнорирует строки - PullRequest
0 голосов
/ 29 июня 2018

У меня есть таблица в SQL Server, где мне нужно фильтровать комнаты по имени и типу. Проблема в том, что имена хранятся как varchar, а также есть комнаты с буквами. Мне нужно отфильтровать комнаты по буквам, прежде чем я смогу сравнить их как int, иначе я получу ошибку.

Вот пример из Room.Name:

030
210a
210b
Lan-Room-A
240

Я могу работать с именами комнат с помощью a или b с LEFT(Rooms.Name, 3), но если я хочу добавить (LEFT(Rooms.Name, 3) BETWEEN 0 and 350 и он достигает Lan-Room-A, он, очевидно, не может преобразовать строку в int. Мне также нужно выполнить дополнительную фильтрацию, например Room.Type = 6.

SELECT
    Room.Name,
    Room.Descr,
    Room.MainUser
WHERE
    LEFT(Room.Name, 1) NOT LIKE '%[0-9]%' 
    AND LEFT(Room.Name, 3) BETWEEN 0 AND 350  
    AND Room.Type = 6

(для простоты удалены некоторые соединения)

Мне просто нужно отфильтровать строки, содержащие строки, перед предложением when, но я понятия не имею, как.

Ребята, у вас есть идеи?

Обратите внимание, что я не могу редактировать базу данных.

Заранее спасибо.

Ответы [ 3 ]

0 голосов
/ 29 июня 2018

Для 2008 года. Пожалуйста, используйте это.

решение-

;WITH CTE AS
(
    SELECT '030' a UNION ALL
    SELECT '210a' UNION ALL
    SELECT '210b' UNION ALL
    SELECT 'Lan-Room-A' UNION ALL
    SELECT '240'
)
SELECT * FROM CTE
WHERE 
PATINDEX('%[0-9]%', a) = 1 AND
1 = CASE WHEN CAST(LEFT(a, 3) AS INT) BETWEEN 0 and 350 THEN 1 ELSE 0 END

OUTPUT

a
----------
030
210a
210b
240

(4 rows affected)
0 голосов
/ 29 июня 2018

Я не понимаю проблему. Вы можете использовать строки:

WHERE Room.Name NOT LIKE '[0-9]%' AND
      LEFT(Room.Name, 3) BETWEEN '0' AND '350' AND  
      Room.Type = 6

Однако я подозреваю, что ваше намерение захвачено:

WHERE Room.Name >= '000' AND
      Room.Name < '351' AND
      Room.Type = 6

Это работает, потому что вы заполнили нулями числа, поэтому сравнение строк будет работать.

0 голосов
/ 29 июня 2018

Вы можете использовать TRY_CAST:

SELECT *
FROM Rooms
WHERE TRY_CAST(LEFT(Rooms.Name, 3) AS INT) BETWEEN 0 and 350;

Демоверсия DBFiddle


Ваш второй подход не гарантированно работает даже при правильной проверке:

WHERE LEFT(Room.Name, 1) NOT LIKE '%[0-9]%' 
  AND LEFT(Room.Name, 3) BETWEEN 0 AND 350  
  and Room.Type = 6

Оптимизатор запросов может проверять условия в любом порядке, поэтому LEFT(Room.Name, 3) BETWEEN 0 AND 350 может привести к ошибке преобразования.

...