SELECT Z.ZAKKODE, Z.ZAKDATE ... FROM Z.ZAKAZY WHERE Z.ZAKAZ IN (23,34,45,67)
Когда заказов немного, с запросом все нормально, когда их больше 500, т.е. Z.ZAKAZ IN (23,34,45,67 и т.д. - здесь длинный список) не работает.
Как можно поменять запрос, чтобы он стал короче?
Меняла так:
Z.ZAKAZ IN (SELECT ZAKAZ, SUM(KURSDIFF) FROM DVIVZAKUP WHERE (ZAKAZ>0) GROUP BY ZAKAZ HAVING SUM(KURSDIFF)<>0)
С подзапросом работает медленно. Таких конструкций с IN может в одном запросе быть несколько.
Есть еще варианты?
Спустя 26 минут, 34 секунды (21.01.2012 - 18:59) dadli написал(а):
Цитата |
Меняла так: Z.ZAKAZ IN (SELECT ZAKAZ, SUM(KURSDIFF) FROM DVIVZAKUP WHERE (ZAKAZ>0) GROUP BY ZAKAZ HAVING SUM(KURSDIFF)<>0) С подзапросом работает медленно |
странно что ето вообшем работает, так как в подзапросе два поля
Спустя 8 минут, 37 секунд (21.01.2012 - 19:07) Лена написал(а):
там все нормально, не оттуда вырезала подзапрос.
Сам запрос большой, он из отчета, где добавляется разная фильрация по заказу, менеджерам и т.д.
Ну пусть будет так:
Z.ZAKAZ IN (SELECT ZAKAZ FROM DVIVZAKUP WHERE (ZAKAZ>0) AND KURSDIFF<>0)
Сам запрос большой, он из отчета, где добавляется разная фильрация по заказу, менеджерам и т.д.
Ну пусть будет так:
Z.ZAKAZ IN (SELECT ZAKAZ FROM DVIVZAKUP WHERE (ZAKAZ>0) AND KURSDIFF<>0)
Спустя 15 минут, 28 секунд (21.01.2012 - 19:23) caballero написал(а):
проиндексируйте zakaz
Спустя 41 минута, 59 секунд (21.01.2012 - 20:05) Лена написал(а):
на поле Zakaz во всех таблицах, которые участвуют в запросе, индексы стоят.
Спустя 2 часа, 3 минуты, 58 секунд (21.01.2012 - 22:09) caballero написал(а):
тогда нужно пробовать заменить IN на JOIN
Спустя 23 минуты, 25 секунд (21.01.2012 - 22:32) UnWind написал(а):
Чего то у меня от этого запроса аж волосы дыбом.
Можно пожалуйста полную версию запроса в студию ? А мы уже подумаем и сделаем покороче.
Можно пожалуйста полную версию запроса в студию ? А мы уже подумаем и сделаем покороче.
Спустя 22 минуты, 19 секунд (21.01.2012 - 22:55) sergeiss написал(а):
Цитата (UnWind @ 21.01.2012 - 23:32) |
Можно пожалуйста полную версию запроса в студию ? |
Присоединяюсь к этому вопросу. У меня вообще такое подозрение, что подзапрос тут вообще не нужен, т.к. данные берутся из одной и той же таблицы. Если это так, то можно и нужно просто правильно написать условие выбора основного (и единственного запроса).
Спустя 4 минуты, 55 секунд (21.01.2012 - 22:59) UnWind написал(а):
sergeiss
У меня те же подозрения)
У меня те же подозрения)
Спустя 18 часов, 58 минут, 46 секунд (22.01.2012 - 17:58) Лена написал(а):
Прошу отнестись с пониманием к тому, что увидите, чтобы не было соответствующих высказываний. Я исхожу из реальной ситуации - уже что есть, то есть, нужны такие исправления запроса, которые минимально затронут систему и ускорят работу.
Через JOIN я делать не могу. Объясняю почему.
Это ERP-система. Система работает с разными типами БД. Плохо получилось с Oracle. Oracle до 9 версии ANSI-join не поддерживает, после 9 - криво. Такое объяснение было получено от программистов компаний, которые пользуются системой и работают с Oracle. Так как отдельного интерфейса работы с Oracle нет, т.е. запросы идут для всех одинаковые, поэтому все соединения таблиц переносятся в WHERE.
Данные тянутся со многих таблиц - заказы, закупки, складские движения по заказам-закупкам, филиал, слой, товары, общие справочники и т.д. В зависимости от внешних фильтров отчета таблицы, как и выбираемые поля, могут добавляться. Плюс добавляется нужная сортировка, группировка и т.д.
Привожу кусок кода, который непосредственно касается запроса:
Через JOIN я делать не могу. Объясняю почему.
Это ERP-система. Система работает с разными типами БД. Плохо получилось с Oracle. Oracle до 9 версии ANSI-join не поддерживает, после 9 - криво. Такое объяснение было получено от программистов компаний, которые пользуются системой и работают с Oracle. Так как отдельного интерфейса работы с Oracle нет, т.е. запросы идут для всех одинаковые, поэтому все соединения таблиц переносятся в WHERE.
Данные тянутся со многих таблиц - заказы, закупки, складские движения по заказам-закупкам, филиал, слой, товары, общие справочники и т.д. В зависимости от внешних фильтров отчета таблицы, как и выбираемые поля, могут добавляться. Плюс добавляется нужная сортировка, группировка и т.д.
Привожу кусок кода, который непосредственно касается запроса:
if(!$doporder) $doporder = 'Z.ZAKAZ';
$sql = "SELECT DISTINCT Z.ZAKAZ, F.SOKRASH AS FNAZ,
FIL.SOKRASH AS FILNAZ, SLOY.A_S1 AS SLOYNAZ,
Z.ZAKKODE, Z.ZAKDATE,
C.FIO AS CONT, M.A_S1 AS MANNAZ,
Z.TOTALSUM, Z.$mons, Z.TOVSUMMA, V.A_S2 AS VALNAZS,
Z.TOTALSUM-Z.$mons AS NEDOPL, Z.$mons-Z.TOVSUMMA AS DOLG,
$extra_field".",Z.OFORMLEN$dopselect ";
$sql .=" FROM UNIPROPS ZSTAT, ";
$sql .="FIRMS F, FIRMS FIL, UNIPROPS M, UNIPROPS V,
UNIPROPS SLOY, PERSONS C$dopfrom, $TABLE Z$from1 ";
$sql .=" (Z.ZAKAZTIP = ZSTAT.PROPCNT) ";
$sql .="AND (Z.FIRMA = F.FIRMA) ";
$sql .="AND (Z.MANAGER = M.PROPCNT) ";
$sql .="AND (Z.FILIAL = FIL.FIRMA) ";
$sql .="AND (Z.COLOR = SLOY.PROPCNT) ";
$sql .="AND (Z.CONTACTER = C.PERSONA) ";
$sql .="AND (Z.VALUTA = V.PROPCNT) $dopfilter ";
$sql .="AND (Z.ZAKDATE BETWEEN ".$conn->DBDate(ReversDateStrPar($DATS));
$sql .=" AND ". $conn->DBDate(ReversDateStrPar($DATPO)).") ";
if($DONTSHOWNULLBALANCE) $sql .="AND (Z.$mons <> Z.TOVSUMMA) ";
switch($TABLE)
{
case 'ZAKUP': $tbl = "DVIVZAKUP ";
$pager->use_count = false;
break;
case 'ZAKAZY': $tbl = "DVIVZAKAZ ";
$pager->use_count = false;
break;
}
$sql .= "AND (Z.ZAKAZ IN (SELECT ZAKAZ
FROM $tbl WHERE (ZAKAZ>0)
GROUP BY ZAKAZ HAVING SUM(KURSDIFF)<>0))
AND (Z.ZAKAZ NOT IN(SELECT DISTINCT ZAKAZ FROM DOPZAKUP WHERE CATEGORY=1842)) ";
$sql .="ORDER BY $doporder, Z.ZAKDATE";
Спустя 1 час, 29 минут, 59 секунд (22.01.2012 - 19:28) caballero написал(а):
а целочисленных ключей нет? прямо по строчным join делаете? а что значит ANSI-join ? объединение идет по индексам если таковые имеются
Спустя 18 минут, 3 секунды (22.01.2012 - 19:46) Лена написал(а):
Все, что вы видите:
$sql .=" (Z.ZAKAZTIP = ZSTAT.PROPCNT) ";
$sql .="AND (Z.FIRMA = F.FIRMA) ";
$sql .="AND (Z.MANAGER = M.PROPCNT) ";
$sql .="AND (Z.FILIAL = FIL.FIRMA) ";
$sql .="AND (Z.COLOR = SLOY.PROPCNT) ";
$sql .="AND (Z.CONTACTER = C.PERSONA) ";
$sql .="AND (Z.VALUTA = V.PROPCNT)
это соединение по полям типа int, конечно. Первичные ключи таблиц.
ANSI-join - тот синтаксис, который мы привыкли видеть в MySQL - с INNER, OUTER и т.д. Oracle его не знает, я не специалист по Oracle, там как-то у них по-другому пишется соединение таблиц.
$sql .=" (Z.ZAKAZTIP = ZSTAT.PROPCNT) ";
$sql .="AND (Z.FIRMA = F.FIRMA) ";
$sql .="AND (Z.MANAGER = M.PROPCNT) ";
$sql .="AND (Z.FILIAL = FIL.FIRMA) ";
$sql .="AND (Z.COLOR = SLOY.PROPCNT) ";
$sql .="AND (Z.CONTACTER = C.PERSONA) ";
$sql .="AND (Z.VALUTA = V.PROPCNT)
это соединение по полям типа int, конечно. Первичные ключи таблиц.
ANSI-join - тот синтаксис, который мы привыкли видеть в MySQL - с INNER, OUTER и т.д. Oracle его не знает, я не специалист по Oracle, там как-то у них по-другому пишется соединение таблиц.
Спустя 15 минут, 51 секунда (22.01.2012 - 20:02) asokol написал(а):
Если у Вас есть возможность проверить запрос, то попробуйте одно из условий переделать с JOIN. Если сработает (что скорей всего), то в первую очередь замените все соответствующие условия на JOIN-ы.
Спустя 5 минут, 26 секунд (22.01.2012 - 20:08) caballero написал(а):
Цитата |
Oracle его не знает, я не специалист по Oracle, там как-то у них по-другому пишется соединение таблиц. |
Раньше так и было включая восьмую версию использовался плюсик вместо join
в современных версиях вроде все по стандарту.
в любом случае нужно просто написать два запроса одни вариант для оракла с его джойном второй для остальных БД
либо написать view для каждой БД (со своим синтаксисом ) а потом уже обращатся одинаково. и кода меньше будет
Спустя 13 минут, 32 секунды (22.01.2012 - 20:21) sergeiss написал(а):
Цитата (caballero @ 22.01.2012 - 21:08) |
либо написать view для каждой БД (со своим синтаксисом ) а потом уже обращатся одинаково. и кода меньше будет |
Подпишусь под этим вариантом. Это будет наиболее рационально.