|
|
|
| Есть запрос Query1:
SELECT Dogovor.Dogovor_Id, Status_Id, DateStatusChanged FROM Dogovor INNER JOIN Status ON Dogovor.Dogovor_Id = Status.Dogovor_Id ORDER BY DateStatusChanged;
Данный запрос возвращает набор данных, который содержит информацию о статусе договоров. Причем, если договор имееет несколько статусов, то последним в наборе оказывается статус, имееющий наибольшее значение в поле DateStatusChanged.
Дальше мне необходимо с помощью другого запроса получить последний (действующий) статус договора. Т.е. найти статус договора с наибольшим значением поля DateStatusChanged.
SELECT Dogovor_Id, Last(Status_ID) As LastStatus_Id, Last(DataStatusChanged) As LastData FROM Query1 GROUP BY Dogovor_Id;
Но к моему огорчению запрос отрабатывает не корректно. До тех пор, пока наибольшему значению поля Status_Id соответствует поле DataStatusChanged с наибольшем значением - все в порядке, но как только например изменить дату статуса таким образом, что она станет меньше даты предыдущего статуса, то запрос возвращает дату одного статуса и Id другого.
Подскажите, как мне составит ь запрос, чтобы он отрабатывал корректно? | |
|
| |
|
|
|
| нужно групировать по дате Last | |
|
| |
|
10 Кб. |
|
| вот небольшой примерчик - поправте если не трудно.
Если во втором запросе применить MAX(DateSatatusChanged) As Max_Date и убрать Last(Status_Id), с помощью еще одного запроса SELECT Dogovor_Id, Max_Date, Status_Id FROM Query2 INNER JOIN Status ON Query2.Dogovor_Id = Status.Dogovor_Id AND Query2.Max_Date = Status.DateStatusChanged;
- то вроде все получается. | |
|
| |
|
|
|
| а так
SELECT Запрос1.Dogovor_Id, Last(Запрос1.DataStatusChanged) AS [Last-DataStatusChanged], Max(Запрос1.Status_Id) AS [Max-Status_Id]
FROM Запрос1
GROUP BY Запрос1.Dogovor_Id; | |
|
| |
|
|
|
| Как показали мои многочисленные эксперименты с Last и Max - они в запросе друг с другом вообще никак не связаны (как скорей всего и другие функции агрегированния) и единственное что их объединяет это то что они возвращают только одно (естественно) значение. Удивительно то, что результат работы Last не зависит от порядка вывода значений в первом запросе отсортированного по дате. | |
|
| |
|
|
|
| В твоем примере все верно. А можно и так:
SELECT Status.Dogovor_Id, Max(Status.DataStatusChanged) AS MaxOfDataStatusChanged, Max(Status.Status_Id) AS MaxOfStatus_Id
FROM Status
GROUP BY Status.Dogovor_Id;
|
Здесь порядок следования полей Max(Status.DataStatusChanged) AS MaxOfDataStatusChanged, Max(Status.Status_Id) AS MaxOfStatus_Id определяет порядок сортировки. Т.е. сначала он отберет Max(Status.DataStatusChanged) AS MaxOfDataStatusChanged, а потом среди них Max(Status.Status_Id) AS MaxOfStatus_Id
В твоем примере ты добился того же самого, двумя последовательными запросами.
Оба способа приемлемы. Просто если тебе первый промежуточный запрос, отбирающий договоры по макс. дате, нигде больше не нужен, то проще сделать одним запросом. | |
|
| |
|
16 Кб. |
|
| Не соглашусь. Здесь мы получим наибольшее значение для поля DataStatusChanged и нибольшее значение для поля Status_Id и никакой гарантии что эти значения будут соответствовать искомому результату. | |
|
| |
|
|
|
| Где-то так:
SELECT T1.Dogovor_Id, T1.DataStatusChanged As LastData, Max(T2.Status_ID) AS LastStatus_Id
FROM Query1 AS T2 INNER JOIN (SELECT T1.Dogovor_Id, Max(T1.DataStatusChanged) AS DataStatusChanged
FROM Query1 AS T1 GROUP BY T1.Dogovor_Id) AS T1
ON (T2.DataStatusChanged = T1.DataStatusChanged) AND (T2.Dogovor_Id = T1.Dogovor_Id)
GROUP BY T1.Dogovor_Id, T1.DataStatusChanged;
|
| |
|
| |
|
|
|
| мысль интерсная, но вот насчет 'GROUP BY T1.Dogovor_Id, T1.DataStatusChanged' я что-то сомневаюсь. Думаю эта группировка лишняя т.к. запрос
(SELECT T1.Dogovor_Id, Max(T1.DataStatusChanged) AS DataStatusChanged
FROM Query1 AS T1 GROUP BY T1.Dogovor_Id)
- однозначно определяет id договора и наибольшую дату по которым возможно определить Status_ID. | |
|
| |
|
|
|
| Согласен, в данном случае можно и без группировки, но тогда для T1.Dogovor_Id, T1.DataStatusChanged нужно применить какую-нибудь статистическую функцию, например First. | |
|
| |
|
|
|
| т.е. это на тот случай если в течении одного дня статус менялся дважды? | |
|
| |
|
|
|
| Нет.
Если в запросе к одному полю применена статистическая функция или группировка, то и к остальным выводимым полям нужно применить подобное.
Вы бы, чем вопросы задавать, сначала попробовали свой вариант. | |
|
| |
|
|
|
| возможно так
SELECT (T1.Dogovor_Id & '=' & T1.DataStatusChanged) As LastIdData, Max(T2.Status_ID) AS LastStatus_Id
FROM Query1 AS T2 INNER JOIN (SELECT T1.Dogovor_Id, Max(T1.DataStatusChanged) AS DataStatusChanged
FROM Query1 AS T1 GROUP BY T1.Dogovor_Id) AS T1
ON (T2.DataStatusChanged = T1.DataStatusChanged) AND (T2.Dogovor_Id = T1.Dogovor_Id)
GROUP BY T1.Dogovor_Id & '=' & T1.DataStatusChanged;
|
затем выбрать из таблицы согласно T1.Dogovor_Id & '=' & T1.DataStatusChanged | |
|
| |