Гость
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Помогите составить супер сложный запрос / 21 сообщений из 21, страница 1 из 1
04.12.2019, 17:02
    #39898227
Vladimir_KZN
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите составить супер сложный запрос
Здравствуйте! Возможно ли такую выборку одним запросом сделать?
Есть 3 таблицы:

products
_____
id | name
1 | tovar1
2 | tovar2
3 | tovar3
4 | tovar4
5 | tovar5

sklads
_____
id | name | delivery_time (срок доставки, дней)
1 | sklad1 | 10
2 | sklad2 | 20
3 | sklad3 | 30

product_to_sklad
_____
id_product | id_sklad | price (цена товара на складе) | count (количество товара на складе)
1 | 1 | 1000 | 4
1 | 2 | 2000 | 5
2 | 1 | 3000 | 3
2 | 2 | 4000 | 4
3 | 1 | 5000 | 1
3 | 3 | 6000 | 3
3 | 2 | 7000 | 3

У каждого товара из таблицы products может быть несколько складов из таблицы sklads, для этого создана таблица product_to_sklad. Нужно при выборке товаров выбрать только 1 склад для каждого товара, удовлетворяющий нескольким условиям:
1. Количество товара на складе не менее 4 штук и минимальный срок доставки
2. Если нет склада удовлетворяющего первое условие, то выбирать склад с наибольшим количеством и наименьшим сроком доставки
3. Если склад не выбран первым двум условиям, то товар выводить, но без данных по складу

На выходе должно получиться:

id | name | id_sklad | delivery_time | price | count
1 | tovar1 | 1 | 10 | 1000 | 4
2 | tovar2 | 2 | 20 | 4000 | 4
3 | tovar3 | 2 | 20 | 7000 | 3
4 | tovar4 | | | |
5 | tovar5 | | | |

Может я преувеличил с супер сложностью, но у меня в 1 запрос это все реализовать не получается, реализовал так, сначала выбираю все товары, далее foreach по товарам с выборкой всех складов и выбор подходящего склада php-условиями, все работает замечательно, за исключением того, что нет возможности сделать сортировку товаров по цене и количеству, так как в первичной выборке этого нет.
Помогите пожалуйста гуру mysql-запросов!
...
Рейтинг: 0 / 0
04.12.2019, 20:31
    #39898311
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите составить супер сложный запрос
Vladimir_KZN
1. Количество товара на складе не менее 4 штук и минимальный срок доставки

Это два условия. И результат наличия такой записи зависит от порядка их применения.

Vladimir_KZN
2. Если нет склада удовлетворяющего первое условие, то выбирать склад с наибольшим количеством и наименьшим сроком доставки
То же самое.
...
Рейтинг: 0 / 0
04.12.2019, 20:44
    #39898314
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите составить супер сложный запрос
На всякий случай - сделал fiddle . Вдруг кто захочет покрутить... В принципе-то несложная задача, если сделать чётким условие.
...
Рейтинг: 0 / 0
05.12.2019, 09:19
    #39898415
Vladimir_KZN
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите составить супер сложный запрос
Akina, спасибо за ответ. Уточню условие, буду использовать if/else для большей ясности
if (Количество товара на складе не менее 4 штук) {
выбираем с минимальным сроком доставки
} else if (выбираем склады с наибольшим количеством) {
выбираем с минимальным сроком доставки
}
...
Рейтинг: 0 / 0
05.12.2019, 10:20
    #39898441
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите составить супер сложный запрос
Лучше так:

1. Если имеются склады с количеством не менее 4 - вернуть склад с наименьшим сроком доставки, если таких несколько, вернуть склад с [указать однозначное условие, либо продолжить цепочку]

иначе

2. Если имеются склады с этим товаром - вернуть склад с наибольшим количеством, если таких несколько - вернуть склад с наименьшим сроком доставки, если таких несколько, вернуть склад с [указать однозначное условие, либо продолжить цепочку]

иначе

3. Вернуть NULL.

Заполните недостающее. Условие может быть любым (да хоть первый в алфавитном порядке), и необязательно одно и то же в разных пунктах. Условие "первый попавшийся" - нежелательно.
...
Рейтинг: 0 / 0
05.12.2019, 10:28
    #39898445
Vladimir_KZN
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите составить супер сложный запрос
Akina,
Все склады имеют разный срок доставки, но на всякий случай тогда дополню
Как то так:

1. Если имеются склады с количеством не менее 4 - вернуть склад с наименьшим сроком доставки, если таких несколько, вернуть склад первый в алфавитном порядке

иначе

2. Если имеются склады с этим товаром - вернуть склад с наибольшим количеством, если таких несколько - вернуть склад с наименьшим сроком доставки, если таких несколько, вернуть склад первый в алфавитном порядке

иначе

3. Вернуть NULL.

Также я попытался реализовать запрос, выводит только 1 товар, далее разобраться не могу. Вот что получилось

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
SELECT p.id, p.name, s.id AS id_sklad, s.delivery_time, p2s.price, p2s.cnt FROM products p
LEFT JOIN product_to_sklad p2s ON (p.id = p2s.id_product) 
LEFT JOIN sklads s ON (s.id = p2s.id_sklad)
WHERE if (
p2s.cnt >=4,
s.delivery_time = (SELECT min(s2.delivery_time) FROM sklads s2 
        LEFT JOIN product_to_sklad p2s2 ON (s2.id = p2s2.id_sklad) 
        WHERE p2s2.id_product = p.id),
p2s.cnt = (SELECT max(p2s3.cnt) FROM product_to_sklad p2s3
        WHERE p2s3.id_product = p.id) 
        AND s.delivery_time = (
                SELECT min(s4.delivery_time) FROM sklads s4
                LEFT JOIN product_to_sklad p2s4 ON (s4.id = p2s4.id_sklad)
                WHERE p2s4.id_product = p.id)
)
...
Рейтинг: 0 / 0
05.12.2019, 11:53
    #39898505
Vladimir_KZN
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите составить супер сложный запрос
Akina, буду очень признателен, если вы мне поможете
...
Рейтинг: 0 / 0
05.12.2019, 12:16
    #39898518
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите составить супер сложный запрос
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
WITH 
cte AS (
SELECT DISTINCT
       ps.id_product,
       CASE WHEN SUM(ps.cnt>=4) OVER (PARTITION BY ps.id_product) >0
            THEN FIRST_VALUE(ps.id_sklad) OVER (PARTITION BY ps.id_product
                                                ORDER BY ps.cnt<4,
                                                         s.delivery_time ASC, 
                                                         s.name ASC) 
            ELSE FIRST_VALUE(ps.id_sklad) OVER (PARTITION BY ps.id_product
                                                ORDER BY ps.cnt DESC, 
                                                         s.delivery_time ASC, 
                                                         s.name ASC)
            END id_sklad
FROM product_to_sklad ps, sklads s
WHERE ps.id_sklad = s.id
)
SELECT p.name, cte.id_sklad, s.delivery_time, ps.price, ps.cnt `count`
FROM products p
LEFT JOIN cte ON p.id = cte.id_product
LEFT JOIN sklads s ON s.id = cte.id_sklad
LEFT JOIN product_to_sklad ps ON (ps.id_product, ps.id_sklad) = (cte.id_product, cte.id_sklad)


fiddle
...
Рейтинг: 0 / 0
05.12.2019, 12:30
    #39898528
Vladimir_KZN
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите составить супер сложный запрос
Akina, Просто супер, работает, спасибо Вам!!! Вот только проблема, у меня MySQL 5.7. Как можно адаптировать запрос под мою версию?
...
Рейтинг: 0 / 0
05.12.2019, 12:51
    #39898538
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите составить супер сложный запрос
Vladimir_KZN
у меня MySQL 5.7. Как можно адаптировать запрос под мою версию?

Можно. Заменяйте оконные функции соотв. коррелированными подзапросами, а итоговый CTE переносите в секцию FROM.

Но имхо разумнее таки обновить версию - сколько можно на старье-то работать?
...
Рейтинг: 0 / 0
05.12.2019, 13:27
    #39898560
Vladimir_KZN
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите составить супер сложный запрос
Akina, Как то так?
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
SELECT p.name, cte.id_sklad, s.delivery_time, ps.price, ps.cnt `count`
FROM products p
LEFT JOIN (SELECT DISTINCT
       ps.id_product,
       CASE WHEN SUM(ps.cnt>=4) OVER (PARTITION BY ps.id_product) >0
            THEN FIRST_VALUE(ps.id_sklad) OVER (PARTITION BY ps.id_product
                                                ORDER BY ps.cnt<4,
                                                         s.delivery_time ASC, 
                                                         s.name ASC) 
            ELSE FIRST_VALUE(ps.id_sklad) OVER (PARTITION BY ps.id_product
                                                ORDER BY ps.cnt DESC, 
                                                         s.delivery_time ASC, 
                                                         s.name ASC)
            END id_sklad
FROM product_to_sklad ps, sklads s
WHERE ps.id_sklad = s.id
) cte
LEFT JOIN cte ON p.id = cte.id_product
LEFT JOIN sklads s ON s.id = cte.id_sklad
LEFT JOIN product_to_sklad ps ON (ps.id_product, ps.id_sklad) = (cte.id_product, cte.id_sklad)



Ругается на "OVER (PARTITION ... "
...
Рейтинг: 0 / 0
05.12.2019, 13:42
    #39898565
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите составить супер сложный запрос
Vladimir_KZN
Ругается на "OVER (PARTITION ... "
Ну я же вроде сказал:
Akina
Заменяйте оконные функции соотв. коррелированными подзапросами
...
Рейтинг: 0 / 0
05.12.2019, 13:50
    #39898572
Vladimir_KZN
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите составить супер сложный запрос
Akina, эх, если бы я знал что такое оконные функции... , то наверное бы смог заменить. А так я прошу вашей помощи снова
...
Рейтинг: 0 / 0
05.12.2019, 14:09
    #39898588
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите составить супер сложный запрос
Не, слишком это муторно. Мне - лень.
...
Рейтинг: 0 / 0
05.12.2019, 14:18
    #39898592
Vladimir_KZN
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите составить супер сложный запрос
Akina,

Я так понимаю это
Код: sql
1.
 OVER (PARTITION BY ps.id_product)

оконная функция? Может на словах объясните на какой подзапрос ее нужно поменять?
...
Рейтинг: 0 / 0
05.12.2019, 16:10
    #39898698
Vladimir_KZN
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите составить супер сложный запрос
Кто то еще может предложить решение? Для MySQL 5.7?
...
Рейтинг: 0 / 0
05.12.2019, 16:18
    #39898703
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите составить супер сложный запрос
Vladimir_KZN

Нужно при выборке товаров выбрать только 1 склад для каждого товара, удовлетворяющий нескольким условиям:
1. Количество товара на складе не менее 4 штук и минимальный срок доставки
2. Если нет склада удовлетворяющего первое условие, то выбирать склад с наибольшим количеством и наименьшим сроком доставки
3. Если склад не выбран первым двум условиям, то товар выводить, но без данных по складу


Вот эти условия

author1. минимальный срок доставки
2. Если нет склада удовлетворяющего первое условие, то выбирать склад с наибольшим количеством и наименьшим сроком доставки
3. Если склад не выбран первым двум условиям, то товар выводить, но без данных по складу


очень плохо будет делать через один запрос

Даже если это можно написать, (в чём я не сомневаюсь) делать это не нужно,
напиши процедуру или программную логику.
...
Рейтинг: 0 / 0
05.12.2019, 17:16
    #39898746
Vladimir_KZN
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите составить супер сложный запрос
MasterZiv
Vladimir_KZN

Нужно при выборке товаров выбрать только 1 склад для каждого товара, удовлетворяющий нескольким условиям:
1. Количество товара на складе не менее 4 штук и минимальный срок доставки
2. Если нет склада удовлетворяющего первое условие, то выбирать склад с наибольшим количеством и наименьшим сроком доставки
3. Если склад не выбран первым двум условиям, то товар выводить, но без данных по складу


Вот эти условия

author1. минимальный срок доставки
2. Если нет склада удовлетворяющего первое условие, то выбирать склад с наибольшим количеством и наименьшим сроком доставки
3. Если склад не выбран первым двум условиям, то товар выводить, но без данных по складу


Не совсем понял что вы имеете ввиду
MasterZiv

очень плохо будет делать через один запрос

Даже если это можно написать, (в чём я не сомневаюсь) делать это не нужно,
напиши процедуру или программную логику.

Нужно именно одним запросом

Вы можете мне помочь? Под MySQL 5.7?
...
Рейтинг: 0 / 0
05.12.2019, 18:02
    #39898783
Vladimir_KZN
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите составить супер сложный запрос
Задачка актуальна. Прошу помочь составить запрос
...
Рейтинг: 0 / 0
10.12.2019, 12:48
    #39900760
Vladimir_KZN
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите составить супер сложный запрос
Up
...
Рейтинг: 0 / 0
16.12.2019, 14:07
    #39903456
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите составить супер сложный запрос
Не совсем понял что вы имеете ввиду

Что же тут может быть непонятного? Русским же языком написано.

MasterZiv

очень плохо будет делать через один запрос

Даже если это можно написать, (в чём я не сомневаюсь) делать это не нужно,
напиши процедуру или программную логику.


Нужно именно одним запросом

НЕ НУЖНО одним запросом

Вы можете мне помочь? Под MySQL 5.7?

Я даже не буду пытаться. Это бесполезно. Запрос в реальной жизни работать не будет быстро.
...
Рейтинг: 0 / 0
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Помогите составить супер сложный запрос / 21 сообщений из 21, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]