|
Подзапросы с Выбрать Первые | ☑ | ||
---|---|---|---|---|
0
Serginio1
16.08.11
✎
11:19
|
Часто нужно использовать аналог Выбрать первые отсортированные по нескольким полям. Нашел решение такое
ВЫБРАТЬ ПЕРВЫЕ 1000 РеализацияТоваровУслуг.Ссылка, ВложенныйЗапрос.НомерСтроки ИЗ Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг ЛЕВОЕ СОЕДИНЕНИЕ (ВЫБРАТЬ РеализацияТоваровУслугТовары.Ссылка КАК Ссылка, РеализацияТоваровУслугТовары.НомерСтроки КАК НомерСтроки ИЗ Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТоваровУслугТовары ГДЕ (РеализацияТоваровУслугТовары.Ссылка, РеализацияТоваровУслугТовары.НомерСтроки) В (ВЫБРАТЬ ПЕРВЫЕ 1 Док.Ссылка, Док.НомерСтроки КАК НомерСтроки ИЗ Документ.РеализацияТоваровУслуг.Товары КАК Док ГДЕ Док.Ссылка = РеализацияТоваровУслугТовары.Ссылка УПОРЯДОЧИТЬ ПО НомерСтроки УБЫВ,Количество УБЫВ)) КАК ВложенныйЗапрос ПО РеализацияТоваровУслуг.Ссылка = ВложенныйЗапрос.Ссылка УПОРЯДОЧИТЬ ПО РеализацияТоваровУслуг.Дата Что трансформируется в SELECT TOP 1000 _Document196_Q_000_T_001._IDRRef AS f_2, #V8TblAli1_Q_000_T_002._Q_001_F_001 AS f_3, _Document196_Q_000_T_001._Date_Time AS _sf_1 FROM _Document196 _Document196_Q_000_T_001 WITH(NOLOCK) LEFT OUTER JOIN ( SELECT _Document196_VT4933_Q_001_T_001._Document196_IDRRef AS _Q_001_F_000RRef, _Document196_VT4933_Q_001_T_001._LineNo4934 AS _Q_001_F_001 FROM _Document196_VT4933 _Document196_VT4933_Q_001_T_001 WITH(NOLOCK) WHERE EXISTS( SELECT CAST(1 AS NUMERIC(1,0)) AS f_1 FROM ( SELECT TOP 1 _Document196_VT4933_Q_002_T_001._Document196_IDRRef AS _Q_002_F_000RRef, _Document196_VT4933_Q_002_T_001._LineNo4934 AS _Q_002_F_001 FROM _Document196_VT4933 _Document196_VT4933_Q_002_T_001 WITH(NOLOCK) WHERE _Document196_VT4933_Q_002_T_001._Document196_IDRRef = _Document196_VT4933_Q_001_T_001._Document196_IDRRef ORDER BY _Document196_VT4933_Q_002_T_001._LineNo4934 DESC, _Document196_VT4933_Q_002_T_001._Fld4938 DESC ) #V8TblAli1 WHERE _Document196_VT4933_Q_001_T_001._Document196_IDRRef = #V8TblAli1._Q_002_F_000RRef AND _Document196_VT4933_Q_001_T_001._LineNo4934 = #V8TblAli1._Q_002_F_001) ) #V8TblAli1_Q_000_T_002 ON _Document196_Q_000_T_001._IDRRef = #V8TblAli1_Q_000_T_002._Q_001_F_000RRef ORDER BY _Document196_Q_000_T_001._Date_Time Но выполняется очень долго. Может есть более эффетивное решение |
|||
1
Scooter
16.08.11
✎
11:22
|
а зачем левое соединение?
|
|||
2
Serginio1
16.08.11
✎
11:24
|
А какая разница? Это просто тестовый запрос
|
|||
3
Scooter
16.08.11
✎
11:27
|
(2)а тебя не наталкивает на мысль что (1) приводит к долгому выполнению?
|
|||
4
Axel2009
16.08.11
✎
11:30
|
зачем сортировать по количеству убыв если уже по номеру строки отсортировали?
|
|||
5
Scooter
16.08.11
✎
11:32
|
(4)строки с одинаковым номером но с разным количеством? о_О
|
|||
6
Serginio1
16.08.11
✎
11:32
|
Не а. А если мне реально нужно левое соединение. По идее плпн должен быть такой. отобратать Документы реализации по дате, а затем искать нужный строки по таблицам. Там выполнение для 1000 строк должно быть плевое. Сейчас план посмотю
|
|||
7
Scooter
16.08.11
✎
11:35
|
(6)если тебе реально нужно левое соединение тогда запрос из ГДЕ помещаем во временную табл
и в самый верхний запрос (к которому будет пришлёпано соединение) добавляем ГДЕ из временной табл |
|||
8
fisher
16.08.11
✎
11:36
|
Достаточно просто
РеализацияТоваровУслугТовары.НомерСтроки В (ВЫБРАТЬ ПЕРВЫЕ 1 Док.НомерСтроки КАК НомерСтроки Или вообще изменить корреллирующий подзапрос с ВЫБРАТЬ ПЕРВЫЕ 1 на MAX() |
|||
9
Serginio1
16.08.11
✎
11:42
|
(8) По нескольким полям?
|
|||
10
Serginio1
16.08.11
✎
11:45
|
(7) Да тут не суть, просто Костыли приходится делать где можно просто во вложенном запросе использовать поля таблиц используемых выше, а значит и менее эффективный запрос строит 1С
|
|||
11
Scooter
16.08.11
✎
11:49
|
(10)>значит менее эффективный запрос строит 1С
для тебя это открытие? всегда так было зато универсально |
|||
12
Serginio1
16.08.11
✎
11:56
|
(11) Уж лучше Linq to EF. Спасибо понятно. Вот и приходится прямые запросы генерировать, там где скорость критична.
|
|||
13
Scooter
16.08.11
✎
11:59
|
(12)лучше свои запросы пиши под 1с, так будет более правильно
|
|||
14
fisher
16.08.11
✎
12:05
|
(9) По одному. По номеру строки. Проверка на ссылку лишняя у тебя.
Она дублирует коррелирующее условие. |
|||
15
Axel2009
16.08.11
✎
12:09
|
(5) в пределах одного документа одинаковые номера строк чтоли??
|
|||
16
fisher
16.08.11
✎
12:18
|
Вообще тестовый запрос какой-то дурацкий. Непонятно как к нему относиться, что обсуждать и как оптимизировать, т.к. он заведомо избыточно усложненный.
Для получения аналогичного результата канает простейший запрос с группировкой и MAX() без всяких корреляций и лишних соединений. |
|||
17
Serginio1
16.08.11
✎
12:18
|
(1) Без левого соединения тоже самое, основное время уходит на сканирование и индексацию Таблицы документа
|
|||
18
Serginio1
16.08.11
✎
12:25
|
(16) Пусть и дурацкий, реальные на несколько страниц. Суть получить одну строку, отсортированную по нескольким полям.
Вот такой устроит, максимальный по Сумме и количеству ВЫБРАТЬ ПЕРВЫЕ 1000 РеализацияТоваровУслугТовары.Ссылка КАК Ссылка, РеализацияТоваровУслугТовары.НомерСтроки КАК НомерСтроки, РеализацияТоваровУслугТовары.Ссылка.Дата КАК Дата ИЗ Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТоваровУслугТовары ГДЕ (РеализацияТоваровУслугТовары.Ссылка, РеализацияТоваровУслугТовары.НомерСтроки) В (ВЫБРАТЬ ПЕРВЫЕ 1 Док.Ссылка, Док.НомерСтроки КАК НомерСтроки ИЗ Документ.РеализацияТоваровУслуг.Товары КАК Док ГДЕ Док.Ссылка = РеализацияТоваровУслугТовары.Ссылка УПОРЯДОЧИТЬ ПО Док.Сумма УБЫВ, Док.Количество УБЫВ) УПОРЯДОЧИТЬ ПО Дата |
|||
19
fisher
16.08.11
✎
12:28
|
Я ж уже два раза сказал. Достаточно такого:
ВЫБРАТЬ ПЕРВЫЕ 1000 РеализацияТоваровУслугТовары.Ссылка КАК Ссылка, РеализацияТоваровУслугТовары.НомерСтроки КАК НомерСтроки, РеализацияТоваровУслугТовары.Ссылка.Дата КАК Дата ИЗ Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТоваровУслугТовары ГДЕ РеализацияТоваровУслугТовары.НомерСтроки В (ВЫБРАТЬ ПЕРВЫЕ 1 Док.НомерСтроки КАК НомерСтроки ИЗ Документ.РеализацияТоваровУслуг.Товары КАК Док ГДЕ Док.Ссылка = РеализацияТоваровУслугТовары.Ссылка УПОРЯДОЧИТЬ ПО Док.Сумма УБЫВ, Док.Количество УБЫВ) УПОРЯДОЧИТЬ ПО Дата |
|||
20
Axel2009
16.08.11
✎
12:28
|
(18) ну так это и сравнивай по производительности.
|
|||
21
Serginio1
16.08.11
✎
12:29
|
(19) (20) Смотри 17
|
|||
22
Axel2009
16.08.11
✎
12:36
|
(21) ну напиши "прямой" запрос, который будет при данных индексах работать быстрее. гыгы
|
|||
23
Serginio1
16.08.11
✎
12:41
|
Ну думаю CTE должны отрабатывать значительно быстрее.
|
|||
24
Axel2009
16.08.11
✎
12:42
|
(23) пиши в условиях T-SQL, а не в условиях SQL Server. потому как базульки не только на скуле крутятся.
|
|||
25
Axel2009
16.08.11
✎
12:43
|
ВЫБРАТЬ
РеализацияТоваровУслугТовары.Ссылка КАК Ссылка, РеализацияТоваровУслугТовары.НомерСтроки КАК НомерСтроки, РеализацияТоваровУслугТовары.Ссылка.Дата КАК Дата, РеализацияТоваровУслугТовары.Сумма КАК Сумма, РеализацияТоваровУслугТовары.Количество КАК Количество ПОМЕСТИТЬ РеализацияТоваровУслугТовары ИЗ Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТоваровУслугТовары ВНУТРЕННЕЕ СОЕДИНЕНИЕ (ВЫБРАТЬ ПЕРВЫЕ 1000 РеализацияТоваровУслуг.Ссылка КАК Ссылка ИЗ Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг УПОРЯДОЧИТЬ ПО РеализацияТоваровУслуг.Дата) КАК РеализацияТоваровУслуг ПО РеализацияТоваровУслугТовары.Ссылка = РеализацияТоваровУслуг.Ссылка ИНДЕКСИРОВАТЬ ПО НомерСтроки, Сумма, Количество, Ссылка, Дата ; //////////////////////////////////////////////////////////////////////////////// ВЫБРАТЬ РеализацияТоваровУслугТовары.Ссылка КАК Ссылка, РеализацияТоваровУслугТовары.НомерСтроки КАК НомерСтроки, РеализацияТоваровУслугТовары.Ссылка.Дата КАК Дата ИЗ РеализацияТоваровУслугТовары КАК РеализацияТоваровУслугТовары ГДЕ (РеализацияТоваровУслугТовары.Ссылка, РеализацияТоваровУслугТовары.НомерСтроки) В (ВЫБРАТЬ ПЕРВЫЕ 1 Док.Ссылка, Док.НомерСтроки КАК НомерСтроки ИЗ РеализацияТоваровУслугТовары КАК Док ГДЕ Док.Ссылка = РеализацияТоваровУслугТовары.Ссылка УПОРЯДОЧИТЬ ПО Док.Сумма УБЫВ, Док.Количество УБЫВ) УПОРЯДОЧИТЬ ПО Дата |
|||
26
Serginio1
16.08.11
✎
12:46
|
24 У меня на SQL Server и использую все премущества
(25) Все тоже самое. Почемуто он сначала проходится по таблице товары, индексирует, затем выбирает топ (70%) |
|||
28
Axel2009
16.08.11
✎
12:48
|
(26) дак используй. тока 1с выкини. она вынуждена как бы придерживаться T-SQL.
|
|||
29
Axel2009
16.08.11
✎
12:48
|
(26) где тоже самое? куда сначала проходит? кого потом индексирует? ты ваще запускал отчет?
|
|||
30
Serginio1
16.08.11
✎
12:50
|
(28) Зачем мне её выкидывать. Я прямые запросы использую там где это действительно приносит явный прирост в скорости (В том числе и пакетные изменения). А там где 1С рулит, то зачем от нё отказываться?
|
|||
31
Axel2009
16.08.11
✎
12:51
|
с индексом промахнулся.
ВЫБРАТЬ РеализацияТоваровУслугТовары.Ссылка КАК Ссылка, РеализацияТоваровУслугТовары.НомерСтроки КАК НомерСтроки, РеализацияТоваровУслугТовары.Ссылка.Дата КАК Дата, РеализацияТоваровУслугТовары.Сумма КАК Сумма, РеализацияТоваровУслугТовары.Количество КАК Количество ПОМЕСТИТЬ РеализацияТоваровУслугТовары ИЗ Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТоваровУслугТовары ВНУТРЕННЕЕ СОЕДИНЕНИЕ (ВЫБРАТЬ ПЕРВЫЕ 1000 РеализацияТоваровУслуг.Ссылка КАК Ссылка ИЗ Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг УПОРЯДОЧИТЬ ПО РеализацияТоваровУслуг.Дата) КАК РеализацияТоваровУслуг ПО РеализацияТоваровУслугТовары.Ссылка = РеализацияТоваровУслуг.Ссылка ИНДЕКСИРОВАТЬ ПО Ссылка, Сумма, Количество, НомерСтроки, Дата ; //////////////////////////////////////////////////////////////////////////////// ВЫБРАТЬ РеализацияТоваровУслугТовары.Ссылка КАК Ссылка, РеализацияТоваровУслугТовары.НомерСтроки КАК НомерСтроки, РеализацияТоваровУслугТовары.Ссылка.Дата КАК Дата ИЗ РеализацияТоваровУслугТовары КАК РеализацияТоваровУслугТовары ГДЕ (РеализацияТоваровУслугТовары.Ссылка, РеализацияТоваровУслугТовары.НомерСтроки) В (ВЫБРАТЬ ПЕРВЫЕ 1 Док.Ссылка, Док.НомерСтроки КАК НомерСтроки ИЗ РеализацияТоваровУслугТовары КАК Док ГДЕ Док.Ссылка = РеализацияТоваровУслугТовары.Ссылка УПОРЯДОЧИТЬ ПО Док.Сумма УБЫВ, Док.Количество УБЫВ) УПОРЯДОЧИТЬ ПО Дата |
|||
32
Axel2009
16.08.11
✎
12:52
|
(30) если писать запросы не умеешь, и только гдето "находишь" решения, то как пишешь прямые запросы, вообще не понимаю.
|
|||
33
Serginio1
16.08.11
✎
12:52
|
(29) Да все как и с предыдущим запосом. Можно Получить запрос по Таблицам с ограничением и выгружать во временную таблицу с индексированием, а вот из него и брать Первые.
Сейчас попробую |
|||
34
Axel2009
16.08.11
✎
12:54
|
ну и промахнулся с выборкой во втором запросе
РеализацияТоваровУслугТовары.Дата КАК Дата конечно |
|||
35
fisher
16.08.11
✎
12:56
|
А если просто в конфигураторе сказать индексировать поле "Сумма"?
|
|||
36
Serginio1
16.08.11
✎
12:57
|
(34) Спасибо вот такой вариант быстро работает
ВЫБРАТЬ ПЕРВЫЕ 10000 РеализацияТоваровУслугТовары.Ссылка КАК Ссылка, РеализацияТоваровУслугТовары.НомерСтроки КАК НомерСтроки, РеализацияТоваровУслугТовары.Ссылка.Дата КАК Дата, РеализацияТоваровУслугТовары.Сумма КАК Сумма, РеализацияТоваровУслугТовары.Количество КАК Количество ПОМЕСТИТЬ РеализацияТоваровУслугТовары ИЗ Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТоваровУслугТовары УПОРЯДОЧИТЬ ПО Дата ИНДЕКСИРОВАТЬ ПО Ссылка, Сумма, Количество, НомерСтроки, Дата ; //////////////////////////////////////////////////////////////////////////////// ВЫБРАТЬ РеализацияТоваровУслугТовары.Ссылка КАК Ссылка, РеализацияТоваровУслугТовары.НомерСтроки КАК НомерСтроки, РеализацияТоваровУслугТовары.Ссылка.Дата КАК Дата ИЗ РеализацияТоваровУслугТовары КАК РеализацияТоваровУслугТовары ГДЕ (РеализацияТоваровУслугТовары.Ссылка, РеализацияТоваровУслугТовары.НомерСтроки) В (ВЫБРАТЬ ПЕРВЫЕ 1 Док.Ссылка, Док.НомерСтроки КАК НомерСтроки ИЗ РеализацияТоваровУслугТовары КАК Док ГДЕ Док.Ссылка = РеализацияТоваровУслугТовары.Ссылка УПОРЯДОЧИТЬ ПО Док.Сумма УБЫВ, Док.Количество УБЫВ) УПОРЯДОЧИТЬ ПО Дата |
|||
37
Axel2009
16.08.11
✎
12:59
|
(36)
РеализацияТоваровУслугТовары.Ссылка.Дата КАК Дата убери |
|||
38
Axel2009
16.08.11
✎
13:01
|
(36)
ВЫБРАТЬ ПЕРВЫЕ 10000 РеализацияТоваровУслугТовары.Ссылка КАК Ссылка, РеализацияТоваровУслугТовары.НомерСтроки КАК НомерСтроки, РеализацияТоваровУслугТовары.Ссылка.Дата КАК Дата, РеализацияТоваровУслугТовары.Сумма КАК Сумма, + Code РеализацияТоваровУслугТовары.Количество КАК Количество ПОМЕСТИТЬ РеализацияТоваровУслугТовары ИЗ Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТоваровУслугТовары УПОРЯДОЧИТЬ ПО Дата ИНДЕКСИРОВАТЬ ПО Ссылка, Сумма, Количество, НомерСтроки, Дата ; ты хоть знаешь что это возвращает?? |
|||
39
Serginio1
16.08.11
✎
13:12
|
(38) Да хрень, сейчас Переделаю с соединением. Но на 100000 работает быстро
|
|||
40
Serginio1
16.08.11
✎
13:15
|
ВЫБРАТЬ
РеализацияТоваровУслугТовары.Ссылка КАК Ссылка, РеализацияТоваровУслугТовары.НомерСтроки КАК НомерСтроки, РеализацияТоваровУслугТовары.Ссылка.Дата КАК Дата, РеализацияТоваровУслугТовары.Сумма КАК Сумма, РеализацияТоваровУслугТовары.Количество КАК Количество ПОМЕСТИТЬ РеализацияТоваровУслугТовары ИЗ Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТоваровУслугТовары ГДЕ РеализацияТоваровУслугТовары.Ссылка.Дата МЕЖДУ ДАТАВРЕМЯ(2011, 1, 1) И ДАТАВРЕМЯ(2011, 8, 16) ИНДЕКСИРОВАТЬ ПО Ссылка, Сумма, Количество ; //////////////////////////////////////////////////////////////////////////////// ВЫБРАТЬ РеализацияТоваровУслугТовары.Ссылка КАК Ссылка, РеализацияТоваровУслугТовары.НомерСтроки КАК НомерСтроки, РеализацияТоваровУслугТовары.Ссылка.Дата КАК Дата ИЗ РеализацияТоваровУслугТовары КАК РеализацияТоваровУслугТовары ГДЕ (РеализацияТоваровУслугТовары.Ссылка, РеализацияТоваровУслугТовары.НомерСтроки) В (ВЫБРАТЬ ПЕРВЫЕ 1 Док.Ссылка, Док.НомерСтроки КАК НомерСтроки ИЗ РеализацияТоваровУслугТовары КАК Док ГДЕ Док.Ссылка = РеализацияТоваровУслугТовары.Ссылка УПОРЯДОЧИТЬ ПО Док.Сумма УБЫВ, Док.Количество УБЫВ) УПОРЯДОЧИТЬ ПО Дата |
|||
41
Serginio1
16.08.11
✎
13:24
|
Генерируется такой запрос
ELECT TOP 10000 #Te85f61ac690c437aaf9abb367656dabb_Q_001_T_001._Q_000_F_000RRef AS f_2, #Te85f61ac690c437aaf9abb367656dabb_Q_001_T_001._Q_000_F_001 AS f_3, _Document196_raevjiwz._Date_Time AS _sf_1 FROM #tt7 #Te85f61ac690c437aaf9abb367656dabb_Q_001_T_001 WITH(NOLOCK) LEFT OUTER JOIN _Document196 _Document196_raevjiwz WITH(NOLOCK) ON #Te85f61ac690c437aaf9abb367656dabb_Q_001_T_001._Q_000_F_000RRef = _Document196_raevjiwz._IDRRef WHERE EXISTS( SELECT CAST(1 AS NUMERIC(1,0)) AS f_1 FROM ( SELECT TOP 1 #Te85f61ac690c437aaf9abb367656dabb_Q_002_T_001._Q_000_F_000RRef AS _Q_002_F_000RRef, #Te85f61ac690c437aaf9abb367656dabb_Q_002_T_001._Q_000_F_001 AS _Q_002_F_001 FROM #tt7 #Te85f61ac690c437aaf9abb367656dabb_Q_002_T_001 WITH(NOLOCK) WHERE #Te85f61ac690c437aaf9abb367656dabb_Q_002_T_001._Q_000_F_000RRef = #Te85f61ac690c437aaf9abb367656dabb_Q_001_T_001._Q_000_F_000RRef ORDER BY #Te85f61ac690c437aaf9abb367656dabb_Q_002_T_001._Q_000_F_003 DESC, #Te85f61ac690c437aaf9abb367656dabb_Q_002_T_001._Q_000_F_004 DESC ) #V8TblAli1 WHERE #Te85f61ac690c437aaf9abb367656dabb_Q_001_T_001._Q_000_F_000RRef = #V8TblAli1._Q_002_F_000RRef AND #Te85f61ac690c437aaf9abb367656dabb_Q_001_T_001._Q_000_F_001 = #V8TblAli1._Q_002_F_001) ORDER BY _Document196_raevjiwz._Date_Time |
|||
42
Serginio1
16.08.11
✎
13:32
|
Хм а вот индексировать то по убыванию нельзя
|
|||
43
Axel2009
16.08.11
✎
13:38
|
(42) пилите шура, пилите (с)
только этот запрос будет выдавать хрень пока будут жалкие попытки выбрать 10000 записей из таблицы товаров. |
|||
44
Serginio1
16.08.11
✎
13:47
|
(43) Ты о чем? запрос нормально работает, если таблица проиндексирована. (Хотя странно что оптимизатор это сам не делает) Но бывают запросы типа
Док.Сумма УБЫВ,Док.Количество,Док.НомерСтроки а в 1С этого уже не сделать. Ладно суть понятна и его решение |
|||
45
Axel2009
16.08.11
✎
14:02
|
(44) о том что в запрос могут попасть далеко не все строки одного документа.
|
|||
46
Serginio1
16.08.11
✎
14:32
|
(45) Ну это же тест. А по 40 попадают все строки, где косяк?
В 41 это последний запрос. (добавил Select top для поиска в gпрфайлере |
|||
47
Axel2009
16.08.11
✎
14:38
|
(46) чем этот тест отличается от того, чтобы получить номер первой строки и его вывести? получится более упорядоченная информация. чем незнаю что и может меняться от каждого выполнения.
|
|||
48
Serginio1
16.08.11
✎
15:23
|
(47) Что меняется? Отбираются строки по дате документа, Сотрируются. Затем отбираются строки по максимуму Сумме и количеству. В 41 добавлено ограниечение на количество в конечном результате для поиска в профайлере. Не более.
Результат по времени тот же самый, сто и без Select TOP 10000 |
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |