Вложенный запрос возвращает неправильное число строк
У меня в mysql запросе происходит что-то фантастическое. Вот мой запрос для вычисления себестоимости:
select inv.price_for_one
from invoice inv,
posinfo pi,
goods g,
stock_item si,
warehouses w
where g.id = :id
and pi.id = w.pos_info_id
and si.warehouses_id = w.id
and g.id = si.goods_id
and inv.stock_item_id = si.id
and pi.client_legal_informations_id = 12
and inv.id = (select max(inv_sub.id)
from invoice inv_sub,
stock_item si_sub
where inv_sub.id in (inv.id)
and inv_sub.warehouses_id = w.id
and inv_sub.archive = false
and inv_sub.expense = false
and inv_sub.stock_item_id = si_sub.id
group by inv_sub.id,
limit 1);
Непонятно почему он возвращает две строки, а должен возвращать только одну, это важное условие. Я выяснил, что подзапрос возвращает две строки, поэтому внешний запрос тоже возвращает два инвойса. Но почему внутренний запрос возвращает две строки?
Я подставил реальные значения во вложенный запрос, чтобы посмотреть, что он возвращает, и получилось так:
select min(inv_sub.id)
from invoice inv_sub,
stock_item si_sub
where inv_sub.id in (285, 286)
and inv_sub.warehouses_id = 623
and inv_sub.archive = false
and inv_sub.expense = false
and inv_sub.stock_item_id = si_sub.id
group by inv_sub.id,
limit 1;
И этот запрос вернул две строки. Что происходит, почему так?
Что-то не помогли советы. Вот такой запрос все равно возвращает две строки, а нужны данные по последней не списанной накладной
SELECT inv.price_for_one AS costPriceGoods
FROM invoice inv,
posinfo pi,
goods g,
stock_item si,
warehouses w
WHERE si.goods_id = g.id
AND pi.client_legal_informations_id = 12
AND w.pos_info_id = pi.id
AND si.warehouses_id = w.id
AND inv.stock_item_id = si.id
AND inv.id = (SELECT DISTINCT inv_sub.id
FROM invoice inv_sub,
stock_item si_sub
WHERE inv_sub.id in (inv.id)
AND inv_sub.warehouses_id = w.id
AND inv_sub.archive = FALSE
AND inv_sub.expense = FALSE
AND inv_sub.stock_item_id = si_sub.id
ORDER BY inv_sub.id
LIMIT 1)
AND g.id = 10121
ORDER BY inv.id;
Причем внутренний запрос возвращает одну строку
SELECT DISTINCT inv_sub.id
FROM invoice inv_sub,
stock_item si_sub
WHERE inv_sub.id in (287, 288)
AND inv_sub.warehouses_id = 205
AND inv_sub.archive = FALSE
AND inv_sub.expense = FALSE
AND inv_sub.stock_item_id = si_sub.id
ORDER BY inv_sub.id
LIMIT 1
Ответы (1 шт):
Начнем с того, что такой запрос просто не выполнится - помешает запятая перед LIMIT 1. У Вас вернутся строки с inv_sub.id=285 и inv_sub.id=286, которые сгруппируются в 2 группы и в них посчитается min(inv_sub.id). Limit должен оставить от этих 2 строк первую (по мнению MySql), но тогда мне не очень ясен смысл этого действия. Ваш запрос можно преобразовать к виду:
select distinct inv_sub.id
from invoice inv_sub,
stock_item si_sub
where inv_sub.id in (285, 286)
and inv_sub.warehouses_id = 623
and inv_sub.archive = false
and inv_sub.expense = false
and inv_sub.stock_item_id = si_sub.id
order by inv_sub.id ASC
limit 1;
вопрос только в том, что будет быстрее
Поправьте меня, если я ошибаюсь: в таблице invoice хранятся накладные, список не списанных накладных по складу 623 мы получим запросом
select inv_sub.id
from invoice inv_sub
where inv_sub.warehouses_id = 623
and inv_sub.archive = false
and inv_sub.expense = false;
последняя в этом списке будет max(inv_sub.id)
, которую и надо искать. Т.е. запрос надо преобразовать к виду
SELECT inv.price_for_one AS costPriceGoods
FROM invoice inv,
posinfo pi,
goods g,
stock_item si,
warehouses w
WHERE si.goods_id = g.id
AND pi.client_legal_informations_id = 12
AND w.pos_info_id = pi.id
AND si.warehouses_id = w.id
AND inv.stock_item_id = si.id
AND inv.id = (SELECT max(inv_sub.id)
FROM invoice inv_sub,
stock_item si_sub
WHERE inv_sub.warehouses_id = w.id
AND inv_sub.archive = FALSE
AND inv_sub.expense = FALSE
AND inv_sub.stock_item_id = si_sub.id
)
AND g.id = 10121
ORDER BY inv.id;