2014-09-01 4 views
2

Мы используем Oracle 10g XE, и мы обнаружили, что следующий запрос не возвращает никакого значения:Математическая операция между двумя колоннами в сравнении

SELECT ref.referencia, 
     ref.descripcio, 
     stock_reservat, 
     stock, 
     stock_p_rebre, 
     (SELECT count(*) 
      FROM ref_numeros_serie num 
      WHERE num.empresa=ref.empresa AND 
       num.referencia=ref.referencia AND 
       num.diposit=1 AND 
       nvl(num.actiu,'N')='S') cnt_nums_serie 
    FROM emp_referencies ref, 
     ref_stk_dip_acu stk 
    WHERE ref.empresa=1 AND 
     ref.referencia='1B' AND 
     stk.empresa=ref.empresa AND 
     stk.referencia=ref.referencia AND 
     stk.diposit=1 AND 
     -- Relevant part 
     (stk.stock - stk.stock_reservat) <> (SELECT count(*) 
              FROM ref_numeros_serie num 
              WHERE num.empresa=ref.empresa AND 
                num.referencia=ref.referencia AND 
                num.diposit=1 AND 
                nvl(num.actiu,'N')='S') 
     -- End of relevant part 
    GROUP BY ref.empresa, 
      ref.referencia, 
      ref.descripcio, 
      stk.stock, 
      stk.stock_reservat, 
      stock, 
      stock_p_rebre 

Так что сравнение между вычитанием и подзапроса было ложным , Но если мы обменивали подзапрос и вычитание так:

SELECT ref.referencia,ref.descripcio, 
     stock_reservat, 
     stock, 
     stock_p_rebre, 
     (SELECT count(*) 
      FROM ref_numeros_serie num 
      WHERE num.empresa=ref.empresa AND 
       num.referencia=ref.referencia AND 
       num.diposit=1 AND 
       nvl(num.actiu,'N')='S') cnt_nums_serie 
    FROM emp_referencies ref, 
     ref_stk_dip_acu stk 
    WHERE ref.empresa=1 AND 
     ref.referencia='1B' AND 
     stk.empresa=ref.empresa AND 
     stk.referencia=ref.referencia AND 
     stk.diposit=1 AND 
     -- Relevant part 
     (SELECT count(*) 
      FROM ref_numeros_serie num 
      WHERE num.empresa=ref.empresa AND 
       num.referencia=ref.referencia AND 
       num.diposit=1 AND 
       nvl(num.actiu,'N')='S') <> (stk.stock - stk.stock_reservat) 
     -- End of relevant part 
    GROUP BY ref.empresa, 
      ref.referencia, 
      ref.descripcio, 
      stk.stock, 
      stk.stock_reservat, 
      stock, 
      stock_p_rebre 

сравнение верно и мы получаем результаты.

Мы постарались следующие случаи:

  • Удаления второй части вычитания так левой часть сравнения stk.stock: мы получаем результаты, правильно
  • Изменения второй части вычитания пути число как этот stk.stock-2: мы получаем результаты, правильно
  • перестановки левую и правую части сравнения, как описано выше: мы получаем результаты, правильно
  • Изменения арифметического оператора как этот (stk.stock+stk.stock_reservat) <> subquery: никаких результатов, некорректные
  • Изменение подзапроса рядом, как этот (stk.stock-stk.stock_reservat) <> 2: мы не получим результаты, правильные

Мы пытались эти случаи с 10г базой данных не ХЕ и имеет такое же поведение. С 11g, с другой стороны, он отлично работает.

Итак, наш вывод состоит в том, что при использовании оракула 10g сравнение между арифметической операцией между двумя столбцами и подзапросом работает только в том случае, если подзапрос находится слева и операция с правой стороны. У кого-то была аналогичная проблема, и как вы обходились/исправляли ее?

EDIT: Я хочу добавить, что это происходит, когда результат подзапроса равен 0, у нас не было проблем с ним в противном случае, то есть оно ведет себя так, как ожидалось.

+0

Попробуйте изменить '(stk.stock - stk.stock_reservat)' to '(stk.stock - NVL (stk.stock_reservat, 0))' и посмотреть, поможет ли это. Поделитесь и наслаждайтесь. –

+0

Мы пробовали это, и это не сработало –

+0

Вы обновлены на всех патчах? Я помню, что у 10g были проблемы, и, как вы заметили, 11 намного стабильнее. –

ответ

0

Ваш запрос может быть упрощена путем использования оговорки факторинга подзапроса, как в:

WITH ns AS (SELECT r.empresa, r.referencia, count(*) as CNT_NUMS_SERIE 
       FROM ref_numeros_serie n 
       INNER JOIN emp_referencies r 
       r.empresa = n.empresa AMD 
       r.referencia = n.referencia 
       WHERE n.diposit = 1 AND 
        NVL(n.actiu, 'N') = 'S' 
       GROUP BY r.empresa, 
         r.referencia) 
SELECT ref.referencia, 
     ref.descripcio, 
     stock_reservat, 
     stock, 
     stock_p_rebre, 
     ns.CNT_NUMS_SERIE 
    FROM emp_referencies ref 
    INNER JOIN ref_stk_dip_acu stk 
    ON stk.empresa = ref.empresa AND 
     stk.referencia = ref.referencia 
    INNER JOIN ns 
    ON ns.empresa = ref.empresa AND 
     ns.referencia = ref.referencia 
    WHERE ref.empresa = 1 AND 
     ref.referencia = '1B' AND 
     stk.diposit = 1 AND 
     -- Relevant part 
     (stk.stock - NVL(stk.stock_reservat, 0)) <> ns.CNT_NUMS_SERIE 
     -- End of relevant part 
    GROUP BY ref.empresa, 
      ref.referencia, 
      ref.descripcio, 
      stk.stock, 
      stk.stock_reservat, 
      stock, 
      stock_p_rebre 

Это позволяет тянуть общее выражение (SELECT COUNT(*)...), и рассматривать его как отдельную таблицу. Я думаю, что это упрощает чтение запроса и может сэкономить время выполнения.

Делитесь и наслаждайтесь.

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