Второй раз пытаюсь получить ответ на cвой вопрос:
Выше приведена структура базы. Опишу все подробно:
Первая таблица это сигнализации, в которой есть лишь id
, firma
и model
. Здесь все понятно. Дальше идет таблица costusers
- здесь хранятся данные о стоимости каждой сигнализации в разных магазинах, т.е. в поле id_sign
хранится id
из таблицы signalizacii
, дальше поле id_user
- это поле которое ссылается на поле uc_id
в таблице uc1
, и поле cost
- это цена.
Таблица uc1
- это все магазины во всех городах.
Нужно просто выбрать все сигнализации из таблицы signalizacii
и добавить еще одно поле в котором будет хранить минимальная цена для конкретного города. Если вдруг случается так что в таблице costusers
нет ни одной цены на какую-то сигнализацию в некотором городе, то нужно вывести 0.
Помогите пожалуйста, бьюсь уже несколько дней над этим запросом... SQL не мое...
Обновление
select signalizacii.*, COALESCE(MIN(CASE WHEN costusers.cost != 0 THEN costusers.cost END), 0)
from signalizacii
left join costusers on id_sign = id
left join uc1 on costusers.id_user = uc1.user_id
where uc1.city = 'Краснодар'
group by signalizacii.id
Вот что я хотел - показалось мне. Но не тут-то было если в таблице costusers не установлена цена на какую-нибудь сигнализацию то эта сигнализация не выводится вообще.
Проблема до сих пор не решена. Прошу помощи... Пожалуйста. Выше приведенный мной результат к сожалению не выводит сигнализацию вообще если цена на нее не установлена ни одним из магазинов указанного города. А она должна выводится но цена должна быть 0. Помогите пожалуйста.
Как я понял, нужно выбрать минимальные цены для всех товаров во всех магазинах, даже если таковые не заданы. Как вариант, можно использовать такой запрос, основанный на том, что предложил уважаемый nick_n_a:
SELECT signalizacii.*, name, coalesce(MIN(cost), 0) FROM uc1
JOIN signalizacii
LEFT JOIN costusers ON costusers.id_user = uc_id
AND costusers.id_sign = id
GROUP BY name, model
Рабочий пример: http://sqlfiddle.com/#!9/c9294/1/0
С отбором по городу:
SELECT signalizacii.*, name, coalesce(MIN(cost), 0) FROM uc1
JOIN signalizacii
LEFT JOIN costusers ON costusers.id_user = uc_id
AND costusers.id_sign = id
WHERE city='Краснодар'
GROUP BY name, model
Не пытаетесь ли вы убить одним камнем двух зайцев? Зачем вообще так нужно все сделать одним SQL запросом? Чего вы этим достигните?
Наверняка список сигнализаций у вас более-менее фиксирован, то есть не меняется каждую секунду. А значит вы можете загрузить одним запросом список всех сигнализаций, сохранить этот список в кеше в нужном порядке. Затем, по мере необходимости, запрашивать цены для какого-то города, при визуализации подставляя в колонку цены по каждой сигнализации.
Подумайте еще так: не столько важно сделать все в один запрос, сколько важно чтобы вы сами смогли понять что тут делается через год или два, когда понадобится очень срочно исправить какой-то баг. В одном случае вы сразу сходу разберетесь что к чему, потратив на исправление 10 минут. В другом случае вы потратите час или два чтобы восстановить ход мысли и вспомнить все хаки, использованные при написании запроса.
Вам надо сначала объединить таблицы costusers
и uc1
, а только потом присоединять их объединение к таблице signalizacii
.
select
signalizacii.*,
ifnull(min(costusers.cost), 0)
from
signalizacii left join
(
costusers join
uc1 on uc1.user_id = costusers.id_user
) on costusers.id_sign = signalizacii.id and uc1.city = 'Краснодар'
group by signalizacii.id
Если Вам не нравится uc1.city = 'Краснодар'
в предложении on
, то можно использовать подзапрос с where
:
select
signalizacii.*,
ifnull(min(t.cost), 0)
from
signalizacii left join
(
select
costusers.id_sign,
costusers.cost
from
costusers join
uc1 on uc1.user_id = costusers.id_user
where uc1.city = 'Краснодар'
) as t on t.id_sign = signalizacii.id
group by signalizacii.id
Смысл в том, что фильтровать по условию uc1.city = 'Краснодар'
Вы должны либо до, либо во время присоединения costusers join uc1
к таблице signalizacii
.
Много LEFT JOIN-ов, лучше бы нулевые цены отдельным UNION-ом сделать, а в остальном работает как просили.
SELECT DISTINCT s.*, ISNULL(m.mincost, 0) AS 'mincost'
FROM #signal_signalizacii s
LEFT JOIN #signal_costusers u ON u.id_sign = s.id
LEFT JOIN #signal_uc1 c ON u.[user_id] = c.uc_id AND c.city = 'Краснодар'
OUTER APPLY (
SELECT MIN(cost) AS 'mincost' FROM #signal_costusers
WHERE id_sign = s.id
AND [user_id] = c.uc_id
AND c.uc_id IS NOT NULL
) m
Можете уточнить все таки в какой базе данных выполняется запрос? это Mysql Oracle PostGre или MsSql
Будь это Oracle, можно было бы использовать аналитические функции : http://www.sql.ru/blogs/oracleandsql/1926, конструкция
MIN(cost) OVER(Partition BY city)
работает именно так как вам нужно. Если уточните бд можно будет искать реализацию схожую с аналитическими функциями в Oracle
Простите не заметил что это Mysql, тогда прошу проверить: http://sqlfiddle.com/#!9/0de13/11
с нулами сами разберетесь тогда на что их заменить:
/*
все сигнализации из таблицы signalizacii */
SELECT s.*
FROM signalizacii s ;
/*
и добавить минимальную цену по городу, т.е. добавляем поле
Город
min_cost_s_c - минимальная цена на сигнализацию по городу
*/
SELECT s.*, u.city, min(c.cost) as min_cost_s_c
FROM signalizacii s
left join costusers c ON s.id = c.id_sign
left join uc1 u ON c.id_user = u.user_id
group by s.id, s.firma, s.model, u.city;
/*
если нужна минимальная цена по городу не зависимо от сигнализации,
просто минимальная цена то делаем так
*/
SELECT s.*, t.city, t.cost
FROM signalizacii s
left join ( select u.city,
min(c.cost) as cost,
max(c.id_sign) as id_sign
from costusers c
left join uc1 u ON c.id_user = u.user_id
GROUP BY u.city) t
ON s.id = t.id_sign;
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
У меня есть таблица с платежами, где помимо суммы платежа хранится баланс человека на момент платежаЯ хотел с помощью триггера mysql сделать...
Не выводиться никакой информации(ошибок тоже нет), хотя таблица не не пустая
Я пытаюсь получить данные из таблицы MySQL, но вылезает одна из этих ошибок: