Имя: Пароль:
1C
 
помогите оптимизировать запрос (sql)
0 Skom
 
19.10.10
06:13
Select
   |                СпрЦен.ParentExt as Ном,
   |                СпрЦен.ID as Цена,
   |                Const.Value as ЗначениеЦена
   |            from (
   |                 select
   |                     Const.objid as спрЦена,
   |                    max(Const.date) as ПоследняяДата
   |                 from _1sconst as Const (nolock)
   |                 where Const.id = $ИсторияРеквизита.Цены.Цена
   |                group by Const.objid
   |                    ) as ПоследниеДаты
   |            left join _1sconst as Const on Const.id = $ИсторияРеквизита.Цены.Цена
   |                            and Const.objid = ПоследниеДаты.спрЦена
   |                            and Const.date = ПоследниеДаты.ПоследняяДата
   |            left join $Справочник.Цены as СпрЦен on СпрЦен.ID = ПоследниеДаты.спрЦена
   |            left join $Справочник.ТипыЦен as спрТЦ on спрТЦ.ID = $СпрЦен.ТипЦен
   |            where
   |            спрТЦ.DESCR = 'Оптовая'


это часть большого запроса.
в общем самое тормозное место
так как периодических реквизитов много

вообще цель - формирование онлайн прайс листа для сайта (сайт находится в одной сети с базой. поэтому данные берутся из базы)
1 Ivan093
 
19.10.10
06:39
Может попробовать подзапрос вынести в ВТ?
2 Skom
 
19.10.10
06:50
(1) не совсем понял
3 Кириллка
 
19.10.10
06:54
(0)принципиально не используешь $ПоследнееЗначение ?
странная традиция использования хинта NOLOCK
4 Skom
 
19.10.10
06:55
(3) как то так сложилось.
кстати интересная затея. надо сравнить скорость работы
с последним значением. да там и подзапрос похожий получится вроде как
5 Skom
 
19.10.10
06:55
счас замучу сравнение
6 Skom
 
19.10.10
06:56
Кириллка
а чем тебе НОУЛОК не нравится?
7 Кириллка
 
19.10.10
06:57
(6)мне?? о_О ты на свой запрос погляди и себе этот вопрос задай.
8 Skom
 
19.10.10
07:26
(3) вспомнил почему. у меня в общем запросе ЮНИОН есть а при ПоследнееЗначение там ОРДЕР БАЙ используется который с ЮНИОН как то у меня не получилось срастить
9 Кириллка
 
19.10.10
07:29
(8)выведи производной таблицей (оберни еще одни селектом), делов-то
10 Skom
 
19.10.10
07:35
(9) не совсем понял как это. объясни плиз.

ТекстЗапроса = "
   |CREATE VIEW price_price as
   |select
   |    Ном.ISFOLDER as ISFOLDER,
   |    Ном.ParentID as ParentID,
   |    Ном.ID as ID,
   |    Ном.DESCR as DESCR,
   |    Ном.CODE as CODE,
   |    '' as Единица,
   |    '' as Опт,
   |    '' as КрупныйОпт
   |from $Справочник.Номенклатура as Ном
   |WHERE Ном.ISFOLDER = 1 and $Ном.НеВключатьВПрайс = 0 and Ном.ISMARK = 0
   |UNION ALL
   |Select
   |    Ном.ISFOLDER as ISFOLDER,
   |    Ном.ParentID as ParentID,
   |    Ном.ID as ID,
   |    Ном.DESCR as DESCR,
   |    Ном.CODE as CODE,
   |    Ед.DESCR as Единица,
   |    $ПоследнееЗначение.Цены.Цена(СпрОпт.ID, GetDate()) as Опт,
   |    $ПоследнееЗначение.Цены.Цена(СпрКрОпт.ID, GetDate()) as КрупныйОпт
   |From $Справочник.Номенклатура as Ном
   |left join
   |  $Справочник.Цены as СпрОпт ON СпрОпт.ParentExt = Ном.ID
   |  and $СпрОпт.ТипЦен = (Select спрТЦ.ID from $Справочник.ТипыЦен as спрТЦ (nolock) Where спрТЦ.DESCR = 'Оптовая')
   |left join
   |  $Справочник.Цены as СпрКрОпт ON СпрКрОпт.ParentExt = Ном.ID
   |  and $СпрКрОпт.ТипЦен = (Select спрТЦ.ID from $Справочник.ТипыЦен as спрТЦ (nolock) Where спрТЦ.DESCR = 'Крупнооптовая')
   |left join
   |    $Справочник.Единицы as СпрЕд on СпрЕд.ID = $ПоследнееЗначение.Цены.Единица(СпрОпт.ID, GetDate())
   |left join
   |    $Справочник.ОКЕИ as Ед on Ед.ID = $СпрЕд.ОКЕИ
   |Where
   |    $Ном.НеВключатьВпрайс = 0 AND Ном.ISFOLDER = 2 and Ном.ISMARK = 0
   |";    

вот сам запрос который с юнионом. но он на сортировку что то ругается.
11 Кириллка
 
19.10.10
07:51
(10)примерно вот так:

CREATE VIEW price_price
AS
   SELECT
       Выборка.ISFOLDER,
       Выборка.ParentID,
       Выборка.ID,
       Выборка.DESCR,
       Выборка.CODE,
       Выборка.Единица,
       Выборка.Опт,
       Выборка.КрупныйОпт
   FROM (-- Выборка
       SELECT
           Ном.ISFOLDER as ISFOLDER,
           Ном.ParentID as ParentID,
           Ном.ID as ID,
           Ном.DESCR as DESCR,
           Ном.CODE as CODE,
           '' as Единица,
           0.00 as Опт,
           0.00 as КрупныйОпт
       FROM $Справочник.Номенклатура as Ном (NOLOCK)
       WHERE
           Ном.ISFOLDER = 1 AND $Ном.НеВключатьВПрайс = 0 AND Ном.ISMARK = 0

       UNION ALL

       SELECT
           Ном.ISFOLDER as ISFOLDER,
           Ном.ParentID as ParentID,
           Ном.ID as ID,
           Ном.DESCR as DESCR,
           Ном.CODE as CODE,
           Ед.DESCR as Единица,
           $ПоследнееЗначение.Цены.Цена(СпрОпт.ID, GetDate()) as Опт,
           $ПоследнееЗначение.Цены.Цена(СпрКрОпт.ID, GetDate()) as КрупныйОпт
       FROM $Справочник.Номенклатура as Ном (NOLOCK)
       LEFT JOIN $Справочник.Цены as СпрОпт (NOLOCK) ON
           СпрОпт.ParentExt = Ном.ID
           AND EXISTS (
               SELECT 1 FROM $Справочник.ТипыЦен as спрТЦ (NOLOCK) WHERE спрТЦ.DESCR = 'Оптовая' AND $СпрОпт.ТипЦен = спрТЦ.ID
           )
       LEFT JOIN $Справочник.Цены as СпрКрОпт (NOLOCK) ON
           СпрКрОпт.ParentExt = Ном.ID
           AND EXISTS (
               SELECT 1 FROM $Справочник.ТипыЦен as спрТЦ (NOLOCK) WHERE спрТЦ.DESCR = 'Крупнооптовая' AND $СпрКрОпт.ТипЦен = спрТЦ.ID
           )
       LEFT JOIN $Справочник.Единицы as СпрЕд (NOLOCK) ON
           СпрЕд.ID = $ПоследнееЗначение.Цены.Единица(СпрОпт.ID, GetDate())
       LEFT JOIN $Справочник.ОКЕИ as Ед (NOLOCK) ON Ед.ID = $СпрЕд.ОКЕИ
       WHERE
           $Ном.НеВключатьВпрайс = 0
           AND Ном.ISFOLDER = 2
           AND Ном.ISMARK = 0
   ) as Выборка
   ORDER BY
       Выборка.ISFOLDER,
       Выборка.DESCR,
       Выборка.CODE,
       Выборка.ParentID
12 Skom
 
19.10.10
08:02
теперь вот такую ошибку выдал гад((
Error converting data type varchar to numeric.
13 Кириллка
 
19.10.10
08:05
(12)я, наверно, погорячился с 0.00
14 Skom
 
19.10.10
08:06
у меня там '' вот так установлено
15 Skom
 
19.10.10
08:06
select
   |            Ном.ISFOLDER as ISFOLDER,
   |            Ном.ParentID as ParentID,
   |            Ном.ID as ID,
   |            Ном.DESCR as DESCR,
   |            Ном.CODE as CODE,
   |            '' as Единица,
   |            '' as Опт,
   |            '' as КрупныйОпт
   |        from $Справочник.Номенклатура as Ном
   |        WHERE Ном.ISFOLDER = 1 and $Ном.НеВключатьВПрайс = 0 and Ном.ISMARK = 0
   |        UNION ALL
   |        Select
   |            Ном.ISFOLDER as ISFOLDER,
   |            Ном.ParentID as ParentID,
   |            Ном.ID as ID,
   |            Ном.DESCR as DESCR,
   |            Ном.CODE as CODE,
   |            Ед.DESCR as Единица,
   |            $ПоследнееЗначение.Цены.Цена(СпрОпт.ID, GetDate()) as Опт,
   |            $ПоследнееЗначение.Цены.Цена(СпрКрОпт.ID, GetDate()) as КрупныйОпт

вот селект лист
16 Skom
 
19.10.10
08:07
хм. переделал селект лист вот так

'' as Единица,
0 as Опт,
0 as КрупныйОпт

заработало
17 Кириллка
 
19.10.10
08:10
несколько матерных слов
18 Skom
 
19.10.10
08:16
(17) делаю два запроса. старый и новый

показывает новый отрабатывает 72% времени старый 28%
19 Skom
 
19.10.10
08:17
хотя по отдельности новый быстрее работает

ничего не пойму
20 Кириллка
 
19.10.10
08:18
(18)а кто сказал, что он будет быстрее :)
убирай order by, он там нафиг не нужен. Позорюсь тут с тобой
21 Кириллка
 
19.10.10
08:20
CHECKPOINT
GO
DBCC DROPCLEANBUFFERS
GO
DBCC FREEPROCCACHE
GO

SET STATISTICS IO ON
SET STATISTICS TIME ON

<твой запрос>

SET STATISTICS TIME OFF
SET STATISTICS IO OFF
22 Кириллка
 
19.10.10
08:20
+21 один запрос замерил, потом второй замерил именно в этой конструкции без самодеятельности
23 Skom
 
19.10.10
08:21
(20) ордер давно убрал. так как у меня это вьюха))
24 Skom
 
19.10.10
08:22
я сделал вот так

select * from price
select * from price_old

вывел план выполнения запроса

и из 100% общего времени показывает что старый выполняется 28% а новый 72%
25 Skom
 
19.10.10
08:23
счас сделаю как ты говоришь
26 Skom
 
19.10.10
08:25
+ ко всему старый запрос возвращает БОЛЬШИЙ набор записей
27 Skom
 
19.10.10
08:27
СТАРЫЙ
CPU time = 1812 ms,  elapsed time = 37759 ms.

НОВЫЙ
CPU time = 438 ms,  elapsed time = 5355 ms.
28 Кириллка
 
19.10.10
08:27
(26)неучто придется почитать твой запрос :(
29 Skom
 
19.10.10
08:28
старый 7085
новый  6640
30 Кириллка
 
19.10.10
08:28
жена, стратегия меняется
31 Skom
 
19.10.10
08:31
(30) э-э-э-э-э
32 Кириллка
 
19.10.10
08:32
UNION ALL

       SELECT
           Ном.ISFOLDER as ISFOLDER,
           Ном.ParentID as ParentID,
           Ном.ID as ID,
           Ном.DESCR as DESCR,
           Ном.CODE as CODE,
           Ед.DESCR as Единица,
           CASE
               WHEN СпрОпт.ID IS NULL
                   THEN 0.00
               ELSE $ПоследнееЗначение.Цены.Цена(СпрОпт.ID, GetDate())
           END as Опт,
           CASE
               WHEN СпрКрОпт.ID IS NULL
                   THEN 0.00
               ELSE $ПоследнееЗначение.Цены.Цена(СпрКрОпт.ID, GetDate())
           END as КрупныйОпт
       FROM $Справочник.Номенклатура as Ном (NOLOCK)
       LEFT JOIN $Справочник.Цены as СпрОпт (NOLOCK) ON
           СпрОпт.ParentExt = Ном.ID
           AND $СпрОпт.ТипЦен = :Оптовая -- <<----
       LEFT JOIN $Справочник.Цены as СпрКрОпт (NOLOCK) ON
           СпрКрОпт.ParentExt = Ном.ID
           AND $СпрКрОпт.ТипЦен = :Крупнооптовая -- <<----
       LEFT JOIN $Справочник.Единицы as СпрЕд (NOLOCK) ON
           СпрЕд.ID = $ПоследнееЗначение.Цены.Единица(СпрОпт.ID, GetDate())
       LEFT JOIN $Справочник.ОКЕИ as Ед (NOLOCK) ON Ед.ID = $СпрЕд.ОКЕИ
       WHERE
           $Ном.НеВключатьВпрайс = 0
           AND Ном.ISFOLDER = 2
           AND Ном.ISMARK = 0
33 Skom
 
19.10.10
08:43
уно моменто
34 Skom
 
19.10.10
08:44
неа как было 6640 так и есть
35 leshikkam
 
19.10.10
08:48
(34) А зачем подключать справочник Единиц и ОКЕИ? И да - в классе ПрямойЗапрос есть ВТ СрезПоследних. Удобней писать.
36 Skom
 
19.10.10
08:49
(35) мне надо вычислить как зовут ту или иную единицу измерения.
в каком классе? ВТ? что за класс.
37 Злопчинский
 
19.10.10
08:57
..читаю...
38 leshikkam
 
19.10.10
09:01
(36)http://www.1cpp.ru/forum/YaBB.pl?num=1285352210
Может обсудим весь запрос? Если что - пиши в icq 201216890.
39 Skom
 
19.10.10
09:14
(37) что читаешь?
40 Кириллка
 
19.10.10
09:20
(39)это он типа закладку сделал - вандал, короче.
принципиальный вопрос: замени GETDATE() на параметр.

и нужно что-то сделать с этим: СпрЕд.ID = $ПоследнееЗначение.Цены.Единица(СпрОпт.ID, GetDate())
41 Кириллка
 
19.10.10
09:30
кстати, а почему ты берешь единицу измерения только для оптовой цены, а для крупнооптовой же может быть другая.

короче, запрос на переработку.
42 Skom
 
19.10.10
10:35
(41) не. единица одинаковая.
GetDate на какой параметр заменить.

я же говорю. это вьюха у нас всегда надо на текущий момент времени
43 Кириллка
 
19.10.10
10:41
(42)отработай запрос без оборачивания в представление. А потом, когда вопросов не будет - заворачивай в функцию с параметрами.
44 Skom
 
19.10.10
10:50
(43) ну в принципе запрос отрабатывает. быстро.
45 Skom
 
19.10.10
10:51
в (40) что ты имел в виду

и нужно что-то сделать с этим: СпрЕд.ID = $ПоследнееЗначение.Цены.Единица(СпрОпт.ID, GetDate())
46 Кириллка
 
19.10.10
11:00
(45)есть мнение, что эту конструкцию нужно переписать.
47 Skom
 
19.10.10
11:07
(46) никак не пойму на что ты намекаешь.
каким образом переписать?
48 el-gamberro
 
19.10.10
11:08
единица переодический реквизит спр цены? это сильно...
49 el-gamberro
 
19.10.10
11:08
(47) он намекает на коррелированный подзапрос.
50 el-gamberro
 
19.10.10
11:09
кстати говорят что в 8.2 наконец-то коррелированные подзапросы появились.
51 Skom
 
19.10.10
11:12
(48) а то)) типовая комплексная))
52 Кириллка
 
19.10.10
11:13
(47)про какие намеки идет речь? :) Тупо сжечь и написать подругому.
53 Skom
 
19.10.10
11:17
(52) я в силу своих познаний скуля смог написать только такое.
ну не без вашей помощи.

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