Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/topic.php on line 737
Форумы портала PHP.SU :: Объединение двух запросов в один

 PHP.SU

Программирование на PHP, MySQL и другие веб-технологии
PHP.SU Портал     На главную страницу форума Главная     Помощь Помощь     Поиск Поиск     Поиск Яндекс Поиск Яндекс     Вакансии  Пользователи Пользователи


 Страниц (1): [1]   

> Описание: хочу избежать запроса в цикле
ivanm
Отправлено: 21 Ноября, 2014 - 14:46:35
Post Id


Новичок


Покинул форум
Сообщений всего: 19
Дата рег-ции: Февр. 2013  


Помог: 0 раз(а)




tlistvg - таблица с данными по транспортному средству
-idn *mediumint * - идент. транспортного средства, автоинскремент
-dnakl *date* - дата накладной(по ней формируется цена в справочнике цен)
-dtinput
-brutto
-tara
-netto
- ...

транспортное средство везет несколько видов продукции.

tscrweight - таблица видов продукции и их вес в тр.средстве
idn *int* - идент.продукции, автоинскремент
listvg *mediumint* - идент. транспортного средства (idn таблицы tlistvg)
scr *smallint* - код вида продукции
scrw - ч.вес по виду

tpricezd - таблица, справочник цен по видам продукции
idn *smallint* - идент., автоинскремент
prdate *date* - дата начала дейст. цены
scr *smallint* - вид продукции((idn таблицы tscrweight)
prf - цена

Таблица справочника цен имеет вид, например:
1 20.04.2014 5 2100
2 05.04.2014 5 2300
...
3 20.04.2014 8 1950
4 06.04.2014 8 1520
...

Необходимо в одном запросе получить:
1. данные по транспортному средству (это понятно)
2. виды которые оно перевозит (и это понятно LEFT JOIN)
3. самое главное, актуальная цена вида из справочника
цен на дату отгрузки транспортного средства (это сейчас реализовано запросом в цикле.).
4.При всем при этом необходимо чтобы запрос выдавал каждой строкой по транспортному
средству, а не по видам - поэтому данные по видам групируются GROUP_CONCAT а потом разбиваются в цикле по explode.

Сейчас это реализовано таким образом:
$query_string="SELECT tlistvg.`idn`, tlistvg.`dnakl`,...,
GROUP_CONCAT(tscrweight.`scr` ORDER BY tscrweight.`idn` ASC SEPARATOR ';') AS grscr,
GROUP_CONCAT(tscrweight.`scrw` ORDER BY tscrweight.`idn` ASC SEPARATOR ';') AS grscrw
FROM `tlistvg`
LEFT JOIN `tscrweight` ON tlistvg.`idn` = tscrweight.`listvg`
GROUP BY tlistvg.`idn` ORDER BY tlistvg.`dtinput` desc";

$result_id = mysql_query($query_string, $link);
while($row = mysql_fetch_array($result_id, MYSQL_ASSOC))
{
...
$grscr=explode(';',$row['grscr']); // расбираем коды видов продукции по этому транспортному средству
$grscrw=explode(';',$row['grscrw']); // и другие данные....
foreach($grscr as $k=>$v){ // для каждого вида ищем актуальную цену(выводим все цены по виду в которых дата цены меньше или равна
.. дате накладной - так как цена формируется по накладной - и берем максимальную дату
$qstr='SELECT tpricezd.`prf' AS pricezd FROM `tpricezd`
WHERE tpricezd.`scr`='.(int)$v." AND tpricezd.`prdate`<='$prdate'
ORDER BY tpricezd.`prdate` DESC LIMIT 1";
$rid = mysql_query($qstr, $link) or die(mysql_error());
$rw = mysql_fetch_array($rid, MYSQL_ASSOC);
$pricezd=decode($rw['pricezd']);
echo '<td>',$pricezd,'</td>'; // искомая цена
}
}

Сразу возникнут вопросы:
1.почему цены нужно выбирать из справочника цен, а не ввести дополнительное поле цены в таблицу по видам?
- Потому что нужно именно так, отправок в день много, а справочник цен может перебиваться задним числом
и изменением одной цены в справочнике - изменять цены по всем отправкам с этой ценой (т.е. не нужно
постоянно перебивать цены по каждому виду в каждой отправке).
По закрытию месяца когда все цены будут отлажены, фиксируем цены уже в табличку по видам.
2. Зачем надо групировать виды по GROUP_CONCAT.
- Затем что обработка первого запроса - это многокилобайтный код...и он изначально написан
под транспортное средство - а потом добавили виды...и все другое...соответственно переписывать
весь код нет ни желания ни времени.

ВООБЩИМ ВОПРОС - можно ли как то вписать указанный в цикле запрос№2 в запрос №1.
 
 Top
LIME
Отправлено: 21 Ноября, 2014 - 19:31:08
Post Id


Активный участник


Покинул форум
Сообщений всего: 10732
Дата рег-ции: Нояб. 2010  


Помог: 322 раз(а)




1. зачем это надо оптимизировать?
2. $grscr=explode(';',$row['grscr']);
явно неправильный формат хранения
следовательно даже если запросы объеденить то получим перебор всех строк ...нет никакого смысла
(Добавление)
$grscr=explode(';',$row['grscr']); - лучше нормализовать...если не понял то лучше все значения разделенные ; вынести в отдельную таблицу
и тогда можно чтото думать
но если нет желания сильно рефакторить то и нечего тут думать
вариантов быть не может
(Добавление)
наиболее легкий в реализации вариант(я очень против) это рисовать кэш
тоесть запрашиваем в цикле и кэшируем результат
ну или
ivanm пишет:
переписывать
весь код нет ни желания ни времени.
а придется
 
 Top
ivanm
Отправлено: 24 Ноября, 2014 - 09:53:12
Post Id


Новичок


Покинул форум
Сообщений всего: 19
Дата рег-ции: Февр. 2013  


Помог: 0 раз(а)




1.Затем что один запрос будет работать гораздо быстрее чем запрос в цикле.
2. $grscr=explode(';',$row['grscr']) устраивает. Тут просто нужно перечислить виды продукции по каждому транспортному средству в таблицу, тем более в GROUP_COMCAT там сортировка стоит-поэтому достаю значения нормально.

Может у кого-то есть еще мысли..
 
 Top
Мелкий Супермодератор
Отправлено: 24 Ноября, 2014 - 10:18:05
Post Id



Активный участник


Покинул форум
Сообщений всего: 11926
Дата рег-ции: Июль 2009  
Откуда: Россия, Санкт-Петербург


Помог: 618 раз(а)




ivanm пишет:
один запрос будет работать гораздо быстрее чем запрос в цикле

На самом деле есть варианты. Группировка с сортировкой штуки тоже не бесплатные.
Особенно в условиях "многокилобайтный код" и "переписывать весь код нет ни желания ни времени"

Выгрузите предварительно массив ценников. Не будет запросов в цикле и не ухудшится производительность первого запроса.


-----
PostgreSQL DBA
 
 Top
ivanm
Отправлено: 24 Ноября, 2014 - 14:15:15
Post Id


Новичок


Покинул форум
Сообщений всего: 19
Дата рег-ции: Февр. 2013  


Помог: 0 раз(а)




Спасибо. В принципе наверное самое логичное решение - еще один запрос с ценниками и потом выбирать из массива.
Ну или переписывать главный запрос уже исходя из позиции множества видов join к транспортному средству..
 
 Top
Страниц (1): [1]
Сейчас эту тему просматривают: 0 (гостей: 0, зарегистрированных: 0)
« Работа с СУБД »


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



Powered by PHP  Powered By MySQL  Powered by Nginx  Valid CSS  RSS

 
Powered by ExBB FM 1.0 RC1. InvisionExBB