Имя: Пароль:
1C
1C 7.7
v7: Самые поздние даты закупок SQL
0 Владимир1С
 
04.03.19
11:00
Есть таблица, с записями о закупках. Кто, когда. Необходимо одним запросом , можно пакетным, получить даты самых последних закупок.
Есть работающий запрос:

SELECT Клиенты.CODE Код
    , MAX(Дисконт.DATE_TIME_IDDOC) ДатаДокумента
FROM $Регистр.Дисконт AS Дисконт With (NOLOCK)
    INNER JOIN $Справочник.Клиенты AS Клиенты With (NOLOCK) ON $Дисконт.Клиент = Клиенты.ID
GROUP BY Клиенты.CODE
ORDER BY Клиенты.COD

Но, методически,кажется, он неверен: нужно брать первое значение Дисконт.DATE , при сортировке по убыванию или последнее при сортировке по возрастанию.
Хотя, сортировка, это опять операция сравнения, как и в функции MAX.
Вопрос: Есть ли возможность исключить сравнения дат, ограничившись только одной выборкой, при которой запрос будет выдавать наружу только последнее выбранное значение, при чём, по каждому отдельному клиенту?
1 viktor_vv
 
04.03.19
11:08
Без сортировки никак . Можешь так попробовать , тут без group by может побыстрее быть

SELECT Клиенты.CODE Код
    , (Select top 1
         Дисконт.DATE_TIME_IDDOC
        From $Регистр.Дисконт AS Дисконт With (NOLOCK)
          Where  $Дисконт.Клиент = Клиенты.ID
           Order by Дисконт.DATE_TIME_IDDOC DESC) as DateLast
FROM $Справочник.Клиенты AS Клиенты With (NOLOCK)
//FROM $Регистр.Дисконт AS Дисконт With (NOLOCK)


ORDER BY Клиенты.COD
2 viktor_vv
 
04.03.19
11:10
И в таблице $Регистр.Дисконт очень желателен составной индекс по полям (Клиент , DATE_TIME_IDDOC )
3 Ёпрст
 
04.03.19
11:10
(0) ну и бери или max или min в тексте запроса.
4 Владимир1С
 
04.03.19
11:21
(1)спасибо. Очень жаль, надеялся на возможность ликвидации операции сравнения. Что MAX, что просто сортировка, один предмет с разных видов.
(2) В то то и дело, хорош этот индекс, когда с самого начала, а так, достраивать его на лету, бессмысленно, с точки зрения времязатрат.
5 viktor_vv
 
04.03.19
11:29
(4) А без сортировки сравнения для этой задачи никак . Так индекс-то там несложно , там как раз на поле Клиент поставить галку отбор движений , как раз и получится составной (Клиент , DATE_TIME_IDDOC) , если правильно помню.
6 Sserj
 
04.03.19
11:38
(0) Смотря какой у тебя SQLServer, если 2005 и выше, то там есть оконные функции, хотя не помню точно в каком развитии, потому что они изначально были не полностью реализованы были. Но в 2008 к примеру можно так:
SELECT
  Клиенты.CODE, Продажи.ДатаДок
FROM
  (SELECT
    $Дисконт.Клиент as Клиент
    , Дисконт.DATE_TIME_IDDOC as ДатаДок
    , ROW_NUMBER() OVER (PARTITION BY $Дисконт.Клиент ORDER BY Дисконт.DATE_TIME_IDDOC DESC) as номерПродажи
  FROM $Регистр.Дисконт AS Дисконт With (NOLOCK)
  ) AS Продажи
  INNER JOIN $Справочник.Клиенты AS Клиенты With (NOLOCK) ON Продажи.Клиент = Клиенты.ID  
WHERE
  Продажи.номерПродажи = 1

Преимущество в том что оконные функции работают в многопоточном режиме.
7 Владимир1С
 
04.03.19
11:46
(6) Большое спасибо, многопоточность буду иметь ввиду, когда перейду с 2005 SQL на другой.
8 Salimbek
 
04.03.19
13:37
(0) Да все у тебя правильно, и при нормальных индексах - должно быстро работать.
9 Salimbek
 
04.03.19
13:40
Если конкретнее, то "исключить сравнения дат" - СКЛ и так не сравнивает даты. Когда задаешь Макс - он тупо берет наибольшее значение из индекса.

Но если же хочешь именно "исключить сравнения дат" - то значит надо создавать отдельный справочник и туда писать дату последней закупки. И учесть, что при отмене проведения какого-либо Документа - надо посмотреть, а вдруг это и есть Дата последней закупки, и если так, то находить предыдущий Док и записывать его дату. Как по мне - то через чур сложно и не стоит оно того.