Имя: Пароль:
1C
1С v8
Что быстрее? Запрос с группировкой по тч или функция Количество() тч?
0 DirecTwiX
 
07.01.14
18:50
Нужно выбрать документы, у которых в ТЧ 1 строка. Группировать или перебор выборки, использую Количество()?

Всё-таки группировка занимает n*ln(n) (минимум)..
1 МихаилМ
 
07.01.14
18:54
если у тч есть поле номерстроки то поможно по нему отбирать.
2 ptitsa-radio
 
07.01.14
18:54
А перебор по-вашему, как работает? ))))
3 ptitsa-radio
 
07.01.14
18:56
ИМХО прямой запрос к таблице ТЧ, минуя шапку даст больше скорости, если считать количество, группируясь по полю Ссылка.
Перебор документов, с вызовом функции Количество() даст все равно неявное соединение двух таблиц, что будет медленнее, чем группировка в одной.
4 DirecTwiX
 
07.01.14
18:58
(2) За один проход? "))))"
Есть массив ссылок, из них нужно отобрать те, у которых в ТЧ 1 элемент

(1) Вариант. Спасибо. Но что по поводу (1)?)
5 ptitsa-radio
 
07.01.14
19:04
Перебор работает путем перебора шапок документа. Они - в одной таблице. Чтобы посчитать количество строк в документе, нужно обратиться ко второй таблице, где хранятся строки.
Т. е. мы берем строку из первой таблицы - шапку, лезем во тороую и считаем там те строки, которые соотв. этой шапке.
Получается соединение двух таблиц по ключевому полю.
Если мы делаем запрос, то мы можем сразу обратиться ко второй таблице, где хранятся строки. В ней есть поле Ссылка (это ссылка на шапку дока в первой таблице) и по нему сгруппироваться.
При этом к первой таблице мы не обращаемся вообще и соединения таблиц не делаем.
Да, за один проход, причем, по одной только таблице мы можем получить количество строк в каждом документе.
А в случае прямого перебора - придется проходить две таблицы, при этом их перемножая.
6 ptitsa-radio
 
07.01.14
19:06
(1) Ну и НомерСтроки, ну и что? В любом документе будет строка с номером один, хрен ли по ней отбираться? Это ничего нам не скажет на тему того, есть ли в нем строка с номером два, и три и т. д.
Можно воспользоваться агрегатной функцией Макс (найти документы у которых максимальный номер строки = 1), но это, один хрен влечет за собой группировку по полю Ссылка в таблице строк документа.
7 DirecTwiX
 
07.01.14
19:09
(5) Ничего не понял, но по-моему ты чего-то не понимаешь)
Группировка имеет сложность O(n*ln(n))
Проход по всем ссылка - O(n)
Вопрос в том, сколько времени получится сэкономить запросом.

(6)...
Если там нет строки с номером 2, то там одна строка.
8 ptitsa-radio
 
07.01.14
19:12
(7) Мне бы хотелось увидеть пример запроса, который бы устанавливал наличие отсутсвия строки с номером 2 )))
9 ptitsa-radio
 
07.01.14
19:15
Ребят, если вы не знаете, что такое декартово произведение двух таблиц, то вам очевидно рано задумываться о производительности.
Возьмите любой учебник про СУБД, почитайте азы теории.
10 DirecTwiX
 
07.01.14
19:22
(8)
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ВедомостьНаВыплатуЗарплатыВБанкФизическиеЛица.Ссылка
ПОМЕСТИТЬ СНесколькимиФизЛицами
ИЗ
    Документ.ВедомостьНаВыплатуЗарплатыВБанк.ФизическиеЛица КАК ВедомостьНаВыплатуЗарплатыВБанкФизическиеЛица
ГДЕ
    ВедомостьНаВыплатуЗарплатыВБанкФизическиеЛица.НомерСтроки = 2
    И ВедомостьНаВыплатуЗарплатыВБанкФизическиеЛица.Ссылка В
            (ВЫБРАТЬ
                А.Ссылка
            ИЗ
                ВсеВедомостиСФизЛицом КАК А)
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ВсеВедомостиСФизЛицом.Ссылка
ИЗ
    ВсеВедомостиСФизЛицом КАК ВсеВедомостиСФизЛицом
        ЛЕВОЕ СОЕДИНЕНИЕ СНесколькимиФизЛицами КАК СНесколькимиФизЛицами
        ПО ВсеВедомостиСФизЛицом.Ссылка = СНесколькимиФизЛицами.Ссылка
ГДЕ
    СНесколькимиФизЛицами.Ссылка ЕСТЬ NULL


полное соединение = декартово произведение. Оно будет всегда..
11 ptitsa-radio
 
07.01.14
19:28
(10) Декартова произведения не случится, если работать только с одной таблицей.

Запрос (шепотом) - трэш и угар ))))
"Ссылка в ПОДЗАПРОС" - настойчиво рекомендую избегать данной конструкции.
12 DirecTwiX
 
07.01.14
19:33
(11) Выдыхай и не позорься.

Подскажи пожалуйста, как избежать ССЫЛКА, если колонка так называется? Или, если я переименую, то тебе станет легче?

Я с одной таблицей и работаю...
13 ptitsa-radio
 
07.01.14
19:42
(12) Только хотела пример запроса написать. Но уже не буду. :-) А то позору не оберешься.
14 DirecTwiX
 
07.01.14
19:46
(13) Судя по твоим ответам, ты правильно сделал, что решил ничего не писать)
В (10) разве что можно было сделать выборку из временной таблицы, но это мелочи
15 zulu_mix
 
07.01.14
20:30
выбрать док.ссылка как ссылка,
количество(док.реквизит) как строквтч
поместить вт
из документ.мойдокумент.имятч как док
сгруппировать по ссылка
;
выбрать ВТ.ссылка
из ВТ как ВТ
где ВТ.строквтч=1
16 ptitsa-radio
 
07.01.14
20:34
(15) тихо ржу
Разбаловали вас этими временными таблицами.
В первом запросе используйте предложение ИМЕЮЩИЕ и будет нормальный фарш.
По всем правилам стандарта. Без всяких виртуальных таблиц.
17 zulu_mix
 
07.01.14
20:36
(16) мало ли что ему приспичит туда навалять. пусть вт использует
18 ptitsa-radio
 
07.01.14
20:41
(17) Не надо использовать ВТ. Надо использовать язык запросов. А ВТ нужно использовать по принципу бритвы Оккама - когда, действительно, без них уж никуда. Ибо любая ВТ, по сути дела - подзапрос. А подзапросов нужно избегать по мере возможности.
Автора я пыталась вразумить, но он что-то разволновался и быстро пришел в негодность.
19 zulu_mix
 
07.01.14
20:42
(18) результаты замеров приведи
20 Ork
 
07.01.14
20:46
(18) Хотелось бы у вас сударыня уточнить по поводу декартова произведения.
Получится ли оно при Left Join, Right Join, Outer Join или InnerJoin соединении. Как повлияет на это произведение наличие индекса по полю связи?
21 zulu_mix
 
07.01.14
20:50
(20) погодь, пусть она сначала замер сделает
22 ptitsa-radio
 
07.01.14
20:54
(21) Вы в своем уме? Шнурки токо поглажу и сразу побегу замерять. :-)
То, о чем я говорю - банальности, доступные любому студенту-первокурснику. Если кому-то недоступно, увы. Где-то человек чего-то недоучил.

Нет, солнце нельзя сбить стрелой из лука. А от объяснений этого научного факта, я, пожалуй, воздержусь. Слишком разный уровень, чтобы было место для дискуссии.
23 zulu_mix
 
07.01.14
20:58
(22) в чем заключается банальность? в твоем неумении пользоваться оптимальными алгоритмами? тут я согласен.
24 Feunoir
 
07.01.14
21:26
На дворе Рождество Христово, а вы такие вещи дьявольские говорите... Количество() по каждой ссылке из выборки - это надо же придумать такое. Для тех, кто в цикле запросы вызывает, в аду отдельная сковородка заготовлена.
25 zulu_mix
 
07.01.14
21:28
(24) ты вовремя. твой выход?
26 Feunoir
 
07.01.14
21:30
(25)
ВЫБРАТЬ
    РеализацияТоваровУслугТовары.Ссылка,
    КОЛИЧЕСТВО(*) КАК КоличествоСтрок
ИЗ
    Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТоваровУслугТовары

СГРУППИРОВАТЬ ПО
    РеализацияТоваровУслугТовары.Ссылка

ИМЕЮЩИЕ
    КОЛИЧЕСТВО(*) = 1
27 Feunoir
 
07.01.14
21:31
запрос выполняется 220 миллисекунд на выборке из 2500 документов, размер результата - 600 строк
28 zulu_mix
 
07.01.14
21:35
(27) а мой?
29 zulu_mix
 
07.01.14
21:40
только на скуле проверяй а не на файловой
30 Feunoir
 
07.01.14
21:48
(28) А вареньем не намазать? Я сейчас, в без пятнадцати двенадцать ночи буду проверять в разных позах, ага.

На файловой, на таких объемах - отличия в пределах погрешности. Медленнее на 4-8 миллисекунд. На SQL будет аналогично. Так как создание временной таблицы само по себе времени требует. И ещё в случае временной таблицы поиск ГДЕ вт.КоличествоСтрок = 1 точно пойдёт фулсканом. В случае единого запроса могут подхватиться индексы.

ВТ оправданы в двух случаях: первое - если выборка сложная и медленная, а результат потом используется в нескольких местах. Второе - для упрощения понимания текста запроса. Оба критерия тут не подходят.
31 zulu_mix
 
07.01.14
22:00
(30) а то что у тебя ИМЕЮЩИЕ выбирает так же как и ГДЕ - ниче?
и да, можно сделать индекс по кол-ву строк
32 zulu_mix
 
07.01.14
22:07
а потом выяснится что надо еще данные других таблиц и понеслась...
33 Шурик71
 
07.01.14
22:22
с (26) может поспорить разве что вот это (индекс по ссылке/НомерСтроки может сыграть) ...


ВЫБРАТЬ
    док.Ссылка
поместить вт
ИЗ
    Документ.РеализацияТоваровУслуг.Товары КАК  док
Где док.НомерСтроки = 2
;
Выбрать док.Ссылка
ИЗ
    Документ.РеализацияТоваровУслуг.Товары КАК  док
Левое соединение вт По док.ссылка = вт.ссылка
Где док.НомерСтроки = 1 и вт.Ссылка есть null


И то не факт...
34 ptitsa-radio
 
08.01.14
04:55
(26) Я бы * заменила конкретным полем, желательно проиндексированным. Та же Ссылка, например.
КОЛИЧЕСТВО(Ссылка) КАК КоличествоСтрок
будет работать быстрее, чем КОЛИЧЕСТВО(*) КАК КоличествоСтрок
Особенно в таблицах, где много столбцов.
Вообще, * в запросах лучше не использовать, а перечислять все нужные столбцы поименно. Реально повышает скорость.
А в остальном - однозначно наиболее рентабельный вариант. Здесь даже и думать нечего, это первый класс, вторая четверть для любого СУБД-шника.

"Школьники пишут запрос" - драма в трех действиях. :-)
35 mistеr
 
08.01.14
05:26
(0)

ВЫБРАТЬ
    ПервыеСтроки.Ссылка
ИЗ
    Справочник1.ТабличнаяЧасть1 КАК ПервыеСтроки
        ЛЕВОЕ СОЕДИНЕНИЕ Справочник1.ТабличнаяЧасть1 КАК ВторыеСтроки
        ПО ПервыеСтроки.Ссылка = ВторыеСтроки.Ссылка
            И ПервыеСтроки.НомерСтроки = 1
            И ВторыеСтроки.НомерСтроки = 2
ГДЕ ВторыеСтроки.Ссылка ЕСТЬ NULL

Без группировки. Без регистрации, без смс.
36 ptitsa-radio
 
08.01.14
05:52
(35) Ну вот только таблицу саму на себя умножил, а так - красота.
Рассказать, как такой запрос будет работать в таблице на 100 000 строк, или сам догадаешься?

Господа, а чем вам так всем группировки не угодили, боюсь спросить? С чего вы вдруг решили, что соединение двух таблиц может быть быстрее, чем группировка?
Патамучта там индыксы? :-)
37 ptitsa-radio
 
08.01.14
05:53
Открою страшную тайну - группировки тоже используют индексы. Причем, гораздо эффективней, чем соединения.
38 catena
 
08.01.14
06:52
Ну кстати, если в (35) взять РАЗЛИЧНЫЕ и убрать лишнее соединение ПервыеСтроки.НомерСтроки = 1, он по замерам лидирует. Проверяла на 34000 документах, результат выборки 15000.
39 ptitsa-radio
 
08.01.14
07:10
(38) Спорим, база файловая? ;-)
40 catena
 
08.01.14
07:13
(39)Не угадала.
41 ptitsa-radio
 
08.01.14
07:20
Какой документ тестили? Меня интересует среднее количество строк в каждом.
42 ptitsa-radio
 
08.01.14
07:21
Сосчитайте, пожалуйста, если не сложно.
43 Нууф-Нууф
 
08.01.14
07:22
Где есть номер строки 1 и нет 2. Тему развели...
44 catena
 
08.01.14
08:01
(41)ТребованиеНакладная. Количество документов 33995, в среднем 7,1 строк, максимально 140, с одной строкой 14921.

Текст1 = "    ВЫБРАТЬ
    |    РеализацияТоваровУслугТовары.Ссылка,
    |    КОЛИЧЕСТВО(НомерСтроки) КАК КоличествоСтрок
    |ИЗ
    |    Документ.ТребованиеНакладная.Материалы КАК РеализацияТоваровУслугТовары
    |
    |СГРУППИРОВАТЬ ПО
    |    РеализацияТоваровУслугТовары.Ссылка
    |
    |ИМЕЮЩИЕ
    |    КОЛИЧЕСТВО(НомерСтроки) = 1       ";
Текст4 = "    ВЫБРАТЬ различные
    |    ПервыеСтроки.Ссылка
    |ИЗ
    |    Документ.ТребованиеНакладная.Материалы КАК ПервыеСтроки
    |        ЛЕВОЕ СОЕДИНЕНИЕ Документ.ТребованиеНакладная.Материалы КАК ВторыеСтроки
    |        ПО ПервыеСтроки.Ссылка = ВторыеСтроки.Ссылка
    |            И ВторыеСтроки.НомерСтроки = 2
    |
    |ГДЕ ВторыеСтроки.Ссылка ЕСТЬ NULL ";

В консоли Текст1 275мс, Текст4 175мс (в среднем на 10 запусках, подсчет только выполнения запроса без вывода)
В замере производительности с перезагрузкой предприятия перед каждым запуском:
http://i017.radikal.ru/1401/6a/06a45404d805.jpg
45 mistеr
 
08.01.14
10:12
(38) РАЗЛИЧНЫЕ - это группировка. Ты как у меня потестируй.

(36) Где тут "умножение"? Левое соединение же.

(37) >Причем, гораздо эффективней, чем соединения.
Вот тут поподробнее, пожалуйста. Раскрой мысль.
46 catena
 
08.01.14
10:29
(45)Это да, с РАЗЛИЧНЫЕ я погорячилась, прошу прощения :)

Но в неизменном виде запрос из (35) поставленной задачи не решает ;)
47 Classic
 
08.01.14
11:02
ВЫБРАТЬ
    РеализацияТоваровУслуг.Ссылка
ИЗ
    Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг
ГДЕ
    РеализацияТоваровУслуг.Товары.НомерСтроки = 1
    И НЕ РеализацияТоваровУслуг.Товары.НомерСтроки = 2
48 Classic
 
08.01.14
11:03
Правда не уверен, что будет быстрее
49 ptitsa-radio
 
08.01.14
11:08
(47) вообще не взлетит )
50 ptitsa-radio
 
08.01.14
11:10
Условие представляет собой тавтологию. Запрос вернет все документы, в которых есть первая строка.
51 catena
 
08.01.14
11:12
(50)Да нет. Выборка же идет из документов, а не из ТЧ.
52 Classic
 
08.01.14
11:14
(50)
Взлетит
53 ptitsa-radio
 
08.01.14
11:19
(51) Точно, не заметила.
Но это означает, что мы имеем неявное соединение двух таблиц: Шапки и ТЧ. Т. к. Выбираем мы по шапке, а условие проверяем в ТЧ.
А может и не соедининеие, а вообще подзапрос. Я в душе не знаю, как 1с такую дикую конструкцию интрепретирует.
Чес говоря,условие выглядит ужасно:
А = 1 И НЕ А = 2
То, что 1с-ка это восприниамет, как должное, чести ей не делает )))
Слабо представляю, как это выглядит после интерпретации в классический SQL.
54 acsent
 
08.01.14
11:19
(52) взлететь то взлетит, но результат совсем не тот будет
55 ptitsa-radio
 
08.01.14
11:21
(54) Как ни странно, но работает.
56 acsent
 
08.01.14
11:21
А если попробовать вместо
ИМЕЮЩИЕ
    КОЛИЧЕСТВО(*) = 1

ИМЕЮЩИЕ
    МАКСИМУМ(НомерСтроки) = 1
57 ptitsa-radio
 
08.01.14
11:25
Один фиг - ИМЕЮЩИЕ + агрегатная функция. Хотя, наверное, МАКСИМУМ в данном случае пошустрее будет, чем счетчик.
58 acsent
 
08.01.14
11:27
(57) но там же индекс есть кластерный по номеру строки
59 ptitsa-radio
 
08.01.14
11:28
(58) Да и по смыслу тоже понятно, что должно быстрей отрабатывать. Даже без индекса.
60 acsent
 
08.01.14
11:29
(59) без индекса не факт
61 acsent
 
08.01.14
11:29
без индекса даже наоборот
62 ptitsa-radio
 
08.01.14
11:31
Ну, в случае максимума, если мы видим строку с номером больше одного, сразу можно исключать из дальнейшей группировки этот док.
А в случаее счетчика мы обязаны сначала все досчтитать, а потом уже смотреть, где сколько строк получилось.
Как-то так.
63 ptitsa-radio
 
08.01.14
11:33
(62) Но это, разумеется очень сильно зависит от того, как СУБД строит план выполнения.
64 ptitsa-radio
 
08.01.14
11:34
Во всяком случае максимум медленее количества работать не должен. Хоть с индексом, хоть без индекса.
65 Нууф-Нууф
 
08.01.14
11:34
ВЫБРАТЬ
    ЛимитноЗаборнаяКартаМатериалы.Ссылка,
    СУММА(ЛимитноЗаборнаяКартаМатериалы.НомерСтроки) КАК НомерСтроки
ИЗ
    Документ.ЛимитноЗаборнаяКарта.Материалы КАК ЛимитноЗаборнаяКартаМатериалы

СГРУППИРОВАТЬ ПО
    ЛимитноЗаборнаяКартаМатериалы.Ссылка

ИМЕЮЩИЕ
    СУММА(ЛимитноЗаборнаяКартаМатериалы.НомерСтроки) = 1
66 mistеr
 
08.01.14
11:34
(46) Вот рабочий вариант

ВЫБРАТЬ
    ПервыеСтроки.Ссылка
ИЗ
    Документ.ПоступлениеТоваровУслуг.Товары КАК ПервыеСтроки
        ЛЕВОЕ СОЕДИНЕНИЕ Документ.ПоступлениеТоваровУслуг.Товары КАК ВторыеСтроки
        ПО ПервыеСтроки.Ссылка = ВторыеСтроки.Ссылка
            И (ВторыеСтроки.НомерСтроки = 2)
ГДЕ
    ПервыеСтроки.НомерСтроки = 1
    И ВторыеСтроки.Ссылка ЕСТЬ NULL

По идее, должно идти только по индексам.
67 Нууф-Нууф
 
08.01.14
11:35
не?
68 acsent
 
08.01.14
11:37
(64) Почему?
69 mistеr
 
08.01.14
11:38
(65) Можно еще добавить ГДЕ НомерСтроки <= 2, и получится оптимальный из всех вариантов с группировкой.
70 acsent
 
08.01.14
11:38
(62) А максимум не нужно разве вначале найти? А найти максимум - это сортировка
71 Нууф-Нууф
 
08.01.14
11:40
(69) зачем условие дополнительное накладывать. просто сложить и результат отфильтровать. зачем еще дополнительный отбор на начальном этапе
72 mistеr
 
08.01.14
11:47
(71) Уменьшить объем данных для группировки. Вдруг там большие ТЧ.
73 Нууф-Нууф
 
08.01.14
11:49
(72) так вроде суммирование не сильно сложная функция.
74 mistеr
 
08.01.14
11:58
(73) Так я не про сложность, а про объем. Объем == I/O.