#sql #sql-server #tsql #type-conversion #numeric
Вопрос:
У меня есть таблица со varchar
столбцом, в котором есть какие-либо значения. Я хотел отфильтровать только числовые значения и сравнить их с другими числами. Но я всегда получаю:
Ошибка преобразования значения varchar «!=»)» в тип данных int
Но !=») там даже не существует
Сначала я подумал, что это может быть там, и просто проверил все требования, даже если числовая проверка уже не удалась. Поэтому я поместил это в подзапрос. Но ошибка все равно случается.
Это мой вопрос:
SELECT CAST(data AS float)
FROM
(SELECT DISTINCT Data
FROM [dbo].[log]
WHERE [Time]>='2021-08-04 00:00:00.000'
AND ISNUMERIC(data) = 1
AND Data NOT LIKE '%[^(0-9-.)]%'
) AS t
WHERE
data > 50
Есть какие-нибудь идеи?
Комментарии:
1. SQL Server не обязан обрабатывать предложения в том порядке, в котором вы думаете;
data>50
их можно легко проанализировать доISNUMERIC(data) = 1
илиData NOT LIKE '%[^(0-9-.)]%'
. Я бы предложил удалить эти 2 пункта и просто использоватьTRY_CONVERT(int, data) > 50
. Или, еще лучше, прекратите хранить числовые данные вvarchar
2. Ну, это не моя база данных, я должен работать с тем, что я получаю. Я предположил, что исправлю одно из положений, как только обнаружу проблему. Просто попробовал
TRY_CONVERT(float, data) IS NOT NULL
вместо этого, но это привело к той же ошибке.3. Я понимаю, что подзапрос обрабатывается в ожидаемом порядке. Я бы поспорил
ISNUMERIC
, что функция иногда возвращает значения, которые не являются действительными числами, например точки и запятые. Из-за того, что вы не конвертируетеData
число в свой подзапрос, это может привести к проблемам в фильтреdata > 50
4. Невозможно
TRY_CONVERT(float, data) IS NOT NULL
вернуть эту ошибку, @JaimeDrq . Предположительно, вы все еще оставили некоторые неявные преобразования в своем запросе.5. Спасибо @Larnu, я сделал несколько тестов, и вы совершенно правы
Ответ №1:
Вы могли бы использовать TRY_CAST
для получения NULL
неверных входных данных — вместо исключения. ISNUMERIC
общеизвестно, что он плохо определяет, действительно ли значение столбца числовое — или нет…..
SELECT
NumericData
FROM
(SELECT DISTINCT
Data,
NumericData = TRY_CAST(data AS float)
FROM
[dbo].[log]
WHERE
[Time]>='2021-08-04 00:00:00.000'
AND Data NOT LIKE '%[^(0-9-.)]%') AS t
WHERE
t.NumericData > 50
и вы могли бы найти оскорбительные данные, используя:
SELECT
data,
NumericData = TRY_CAST(data AS float)
FROM
(SELECT DISTINCT Data
FROM [dbo].[log]
WHERE [Time]>='2021-08-04 00:00:00.000'
AND Data NOT LIKE '%[^(0-9-.)]%') AS t
WHERE
TRY_CAST(data AS float) IS NULL
Комментарии:
1. Спасибо, запрос работает. Но неправильный запрос данных не дает никаких результатов. Но, как я уже сказал, его даже нет в таблице.
Ответ №2:
TRY_CAST()
(или аналогичная функция, безусловно, является правильным подходом. Я хочу отметить, что вы можете упростить свой запрос:
SELECT DISTINCT TRY_CAST(data AS float)
FROM [dbo].[log]
WHERE [Time] >= '2021-08-04' AND
TRY_CAST(data AS float) > 50;
Вам не нужен компонент времени для сравнения времени. Вам не нужно использовать LIKE
, потому TRY_CAST()
что делает это за вас.
Комментарии:
1. Да
LIKE
, это был просто подход, чтобы получить только цифры. Достаточно одного метода.. пока это доставляет то, что я хочу.