Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Вложенный подзапрос не отбирает данные раньше главного!  [new]
Andrey_VP
Member

Откуда:
Сообщений: 145
Здравствуйте, уважаемые участники форума.

Есть таблица T c полем name (varchar).
Запрос Q конвертит T.name в INT, отбирая из T те записи, которые можно отконвертить. Сам по себе запрос Q отлично работает.
Но стоит сделать Q вложенным запросом, и сделать выборку из него, чтобы показать записи >0, как вылезает ошибка конвертации 'a' в int.
SELECT  n
FROM
    (SELECT cast(name as int) n
    FROM
        (SELECT  'a' name
        UNION ALL
        SELECT  '1' name
        UNION ALL
        SELECT '1' name) T
    WHERE isnumeric(name)=1) Q
WHERE n >0

Причём, что интересно, если в приведённом примере запись с 'a' в таблице T поставить не первой, а после '1', то ошибки не будет.

Что же это? Разве вложенный запрос не исполняется первым?
Помогите! Как верно написать запрос?
18 янв 13, 14:15    [13791422]     Ответить | Цитировать Сообщить модератору
 Re: Вложенный подзапрос не отбирает данные раньше главного!  [new]
Glory
Member

Откуда:
Сообщений: 104760
Andrey_VP
Что же это? Разве вложенный запрос не исполняется первым?

Сервер может менять порядок выполнения.

Andrey_VP
Помогите! Как верно написать запрос?

Не хранить числа в символьных полях
18 янв 13, 14:18    [13791460]     Ответить | Цитировать Сообщить модератору
 Re: Вложенный подзапрос не отбирает данные раньше главного!  [new]
iap
Member

Откуда: Москва
Сообщений: 47001
isnumeric(name)=1
не гарантирует конвертируемость в INT
18 янв 13, 14:20    [13791476]     Ответить | Цитировать Сообщить модератору
 Re: Вложенный подзапрос не отбирает данные раньше главного!  [new]
qwerty112
Guest
Andrey_VP
Что же это? Разве вложенный запрос не исполняется первым?

дык, у вас же и преобразование (cast) и проверка (isnumeric) - в одном и том же запросе (уровне запроса, если хотите)
а вот, что будет выполнятся первое select (и соотв. - cast) или WHERE (и соотв. - isnumeric) - это сервер сам решит ...
18 янв 13, 14:21    [13791497]     Ответить | Цитировать Сообщить модератору
 Re: Вложенный подзапрос не отбирает данные раньше главного!  [new]
iap
Member

Откуда: Москва
Сообщений: 47001
Andrey_VP,

совет: используйте проверку на конвертируемость с помощью CASE ... WHEN ... THEN ... END,
причём и в списке SELECT, и в предикате WHERE.

Ну и поиск по форуму отнюдь не безнадёжен :)
18 янв 13, 14:23    [13791509]     Ответить | Цитировать Сообщить модератору
 Re: Вложенный подзапрос не отбирает данные раньше главного!  [new]
Andrey_VP
Member

Откуда:
Сообщений: 145
iap, условие отбора я дал для упрощения, на самом деле оно сложнее и гарантирует конвертацию в INT.

qwerty112, сам запрос Q работает без ошибок.
18 янв 13, 14:24    [13791522]     Ответить | Цитировать Сообщить модератору
 Re: Вложенный подзапрос не отбирает данные раньше главного!  [new]
iap
Member

Откуда: Москва
Сообщений: 47001
Andrey_VP
iap, условие отбора я дал для упрощения, на самом деле оно сложнее и гарантирует конвертацию в INT.
Интересно. Покажете?
18 янв 13, 14:25    [13791531]     Ответить | Цитировать Сообщить модератору
 Re: Вложенный подзапрос не отбирает данные раньше главного!  [new]
Glory
Member

Откуда:
Сообщений: 104760
Andrey_VP
на самом деле оно сложнее и гарантирует конвертацию в INT.

Особенно, если cast(name as int) начнет выполняться до isnumeric(name)=1, да ?
18 янв 13, 14:25    [13791534]     Ответить | Цитировать Сообщить модератору
 Re: Вложенный подзапрос не отбирает данные раньше главного!  [new]
qwerty112
Guest
Andrey_VP
qwerty112, сам запрос Q работает без ошибок.

значит, когда он "сам" - сервер сначала выполняет WHERE
а когда "не сам" - SELECT

остальное здесь сказано - 13791509
18 янв 13, 14:28    [13791558]     Ответить | Цитировать Сообщить модератору
 Re: Вложенный подзапрос не отбирает данные раньше главного!  [new]
Andrey_VP
Member

Откуда:
Сообщений: 145
WHERE NOT name like '%[^0-9]%'
Дробных чисел в таблице нет.
18 янв 13, 14:30    [13791583]     Ответить | Цитировать Сообщить модератору
 Re: Вложенный подзапрос не отбирает данные раньше главного!  [new]
Glory
Member

Откуда:
Сообщений: 104760
Andrey_VP
WHERE NOT name like '%[^0-9]%'
Дробных чисел в таблице нет.

И почему сервер не может совместить операции cast(name as int) и WHERE isnumeric(name)=1 и выполнять их параллельно или в любом порядке ?
18 янв 13, 14:33    [13791608]     Ответить | Цитировать Сообщить модератору
 Re: Вложенный подзапрос не отбирает данные раньше главного!  [new]
Andrey_VP
Member

Откуда:
Сообщений: 145
Glory, не понял Ваш вопрос.

А я вот до сегодняшнего дня думал, что вложенные запросы можно использовать как указание серверу что в какой последовательности выполнять.
18 янв 13, 14:36    [13791638]     Ответить | Цитировать Сообщить модератору
 Re: Вложенный подзапрос не отбирает данные раньше главного!  [new]
Glory
Member

Откуда:
Сообщений: 104760
Andrey_VP
А я вот до сегодняшнего дня думал, что вложенные запросы можно использовать как указание серверу что в какой последовательности выполнять.

Вы сильно ошибались. Ничто не мешает серверу раскрыть скобки и понять, что cast( будет применяться к такомому то полю вложенного запроса. И сделать этот cast( раньше.

Сообщение было отредактировано: 18 янв 13, 14:40
18 янв 13, 14:38    [13791656]     Ответить | Цитировать Сообщить модератору
 Re: Вложенный подзапрос не отбирает данные раньше главного!  [new]
iap
Member

Откуда: Москва
Сообщений: 47001
SELECT
 CAST
 (
  CASE 
   WHEN ISNUMERIC([name])=1
    AND [name] NOT LIKE '%[^0-9 +-]%'
    AND LEN(REPLACE(REPLACE(REPLACE([name],' ',''),'-',''),'+',''))<=10
   THEN CASE WHEN CAST([name] AS BIGINT) BETWEEN -2147483648 AND 2147483647 THEN [name] END
  END AS INT
 ) n
FROM
(
 SELECT 'a' [name]
 UNION ALL SELECT '1'
 UNION ALL SELECT '1'
) T
WHERE
 CAST
 (
  CASE 
   WHEN ISNUMERIC([name])=1
    AND [name] NOT LIKE '%[^0-9 +-]%'
    AND LEN(REPLACE(REPLACE(REPLACE([name],' ',''),'-',''),'+',''))<=10
   THEN CASE WHEN CAST([name] AS BIGINT) BETWEEN -2147483648 AND 2147483647 THEN [name] END
  END AS INT
 )>0;
18 янв 13, 14:38    [13791658]     Ответить | Цитировать Сообщить модератору
 Re: Вложенный подзапрос не отбирает данные раньше главного!  [new]
Andrey_VP
Member

Откуда:
Сообщений: 145
iap, спасибо за подробнейший запрос.
18 янв 13, 14:41    [13791692]     Ответить | Цитировать Сообщить модератору
 Re: Вложенный подзапрос не отбирает данные раньше главного!  [new]
iap
Member

Откуда: Москва
Сообщений: 47001
Andrey_VP
iap, спасибо за подробнейший запрос.
Его можно было обнаружить в поиске, и не раз! :)
18 янв 13, 14:44    [13791710]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить