Сложная выборка SQL

12
D
На сайте с 28.06.2008
Offline
977
560

Есть запрос вида


SELECT t1.*,t3.value,t3.year FROM firms AS t1
LEFT JOIN address AS t2 ON t1.id = t2.item_id
LEFT JOIN price AS t3 ON t3.item_id = t1.id
WHERE t1.category_id = '25' and t3.year = '2018'
GROUP BY t1.id
ORDER BY `t3`.`value` DESC

Этот запрос строит таблицу цен по убывания в нужном регионе. Но задача выводить все фирмы региона (FROM firms WHERE t1.category_id = '25' ), даже те, для которых цены нет.

Т.е. нужно показывать те фирмы для которых есть значения t3.year = '2018'

и те - для которых вообще нет записей в price.

Думал, крутил - единственное что придумал - пройтись циклом по всей таблице firms и если в таблице price для t3.item_id = t1.id нет значения 2018 года - написать туда для этих t3.item_id = t1.id

value = 0
year = 0

А запрос переписать так


SELECT t1.*,t3.value,t3.year FROM firms AS t1
LEFT JOIN address AS t2 ON t1.id = t2.item_id
LEFT JOIN price AS t3 ON t3.item_id = t1.id
WHERE t1.category_id = '26' and (t3.year = '2018' or t3.year = '0')
GROUP BY t1.id
ORDER BY `t3`.`value` DESC

Теперь все работает - в таблицу выводятся значения за 2018 год, а в самом низу таблицы - фирмы без цен.

Но какой-то говнокод. Может быть есть более элегантное решение?

Как сделать выборку WHERE t1.category_id = '25' and t3.year = '2018' + те фирмы для которых вообще цен нет?

edogs software
На сайте с 15.12.2005
Offline
714
#1
Т.е. нужно показывать те фирмы для которых есть значения t3.year = '2018'
и те - для которых вообще нет записей в price.

( t3.year = 2018 or t3.year is null)

---------- Добавлено 12.09.2019 в 12:58 ----------

Этот запрос строит таблицу цен по убывания в нужном регионе.
Исходя из ответа в предыдущем топике, Вы же понимаете, что если в группе t1.id окажется несколько t3.value строк, то в t3.value будет произвольное из них значение? Т.е. если для одной фирмы есть цена 100р и 200р, а для другой 150р, то порядок вывода фирм будет неопределённым. Может оказаться как 100р и 150р в выборке, так и 150р и 200р в выборке.
Разработка крупных и средних проектов. Можно с криптой. Разумные цены. Хорошее качество. Адекватный подход.
D
На сайте с 28.06.2008
Offline
977
#2

edogs, это было первое что я попробовал, но дело в том что если в таблице t3 для фирмы нет цены - то там вообще нет записей для t3.item_id = t1.id

и or t3.year is null не работает вероятно потому что выше условие - LEFT JOIN price AS t3 ON t3.item_id = t1.id

---------- Добавлено 12.09.2019 в 13:05 ----------

edogs:
( в группе t1.id окажется несколько t3.value строк,

этого не случится - там же еще сортировка по году, а для 1 года всегда одна цена

edogs software
На сайте с 15.12.2005
Offline
714
#3
Dram:
edogs, это было первое что я попробовал, но дело в том что если в таблице t3 для фирмы нет цены - то там вообще нет записей для t3.item_id = t1.id
и or t3.year is null не работает вероятно потому что выше условие - LEFT JOIN price AS t3 ON t3.item_id = t1.id

Не.

left join как раз и сделан, что бы левая таблица (в данном случае т1) была всегда, а из правой присоединялись бы значения только при выполнении условия лефт джоин. Результат уже фильтруется where и having.

Так что там что-то в другом месте пошло не так.

D
На сайте с 28.06.2008
Offline
977
#4

edogs, я понял почему не срабатывал как надо.

Во первых был мой мусор

value = 0
year = 0

когда его убрал ваш вариант работал но выбирал не все значения.

Оказывается в выборку не попадают фирмы если у них нет цен за 2018 год но есть за како-то другой.

Пытаюсь понять как их теперь добавить в запрос

---------- Добавлено 12.09.2019 в 13:24 ----------

Все нашел решение

(t3.year = '2018' or t3.year is null or t3.year != '2018')



---------- Добавлено 12.09.2019 в 13:24 ----------

edogs, спасибо!

edogs software
На сайте с 15.12.2005
Offline
714
#5
Dram:

Все нашел решение
(t3.year = '2018' or t3.year is null or t3.year != '2018')
edogs, спасибо!

Решение-то так себе 😂

"Если год = 2018 или год не равен 2018 или год вообще отсутствует" - такое условие можно было бы и не писать, т.к. оно покрывает все варианты.

D
На сайте с 28.06.2008
Offline
977
#6

Казалось бы да - но на удивление по всем регионам стало работать как и нужно, я там еще на финальном этапе сортирую год - короче работает как нужно теперь :)

edogs software
На сайте с 15.12.2005
Offline
714
#7
Dram:
Казалось бы да - но на удивление по всем регионам стало работать как и нужно, я там еще на финальном этапе сортирую год - короче работает как нужно теперь :)

Вы убрали условие по году.

То есть теперь в т3.валуе у Вас может быть цена за любой год, т.к. фильтра по году нет.

В частности для фирмы у которой есть цена за 18 год - в выборке может оказаться цена за 15 год.

Год на финальном этапе бесполезно сортировать, т.к. он во-первых не связан с ценой при выборке в группе, а во-вторых опять же может оказаться любым.

D
На сайте с 28.06.2008
Offline
977
#8

Да, вы правы - не туда посмотрел... запутался уже, куча файлов открыта... думаю дальше..

---------- Добавлено 12.09.2019 в 14:24 ----------

мде.. без вариантов - только вариант с говнокодом что я изначально и придумал


value = 0
year = 0
edogs software
На сайте с 15.12.2005
Offline
714
#9

Dram,

По уму Вам надо в таблицу фирм добавить поле в котором будет цена за последний год. И это будет не говнорешение, а вполне хорошее. Задавать можно одним запросом.

А одним запросом можете попробовать как-то так

SELECT t1.*,t3.value,t3.year,
max(concat_ws('.',t3.year,100*t3.value)) max3
FROM firms AS t1
LEFT JOIN address AS t2 ON t1.id = t2.item_id
LEFT JOIN price AS t3 ON t3.item_id = t1.id
WHERE t1.category_id = '25' and t3.year<=2018
GROUP BY t1.id
ORDER BY `t3`.`value` DESC

Результат смотреть в max3, разбирать на php

S
На сайте с 30.09.2016
Offline
459
#10
edogs:
По уму Вам надо в таблицу фирм добавить поле в котором будет цена за последний год. И это будет не говнорешение, а вполне хорошее.

Если ума нет, то да, по уму. Раздувать таблицу, добавляя туда всё новые и новые поля, тем более, когда это уже рабочая таблица, а не проект в разработке - воистину гениальное решение.

P.S. А потом появляются такие вот темы.

Отпилю лишнее, прикручу нужное, выправлю кривое. Вытравлю вредителей.
12

Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий