#sql #sql-server
#sql #sql-сервер
Вопрос:
Моя база данных SQL Server включает в себя все контракты. мой запрос находит значение контракта для последней даты, мне нужен другой столбец, который показывает значение контракта для предпоследнего контракта.
Пример:
ContractID ordd_mn_end_date ord_mn_billed_amt
-------------------------------------------------
8198 10-31-2021 2574.43
8198 10-31-2020 833.15
Чего бы я хотел, так это чтобы ExpiringAmt 2 показывал 833.15
Код
SELECT
det.ordd_ContractItemID,
det.ordd_mn_end_date,
det.ordd_mn_billed_amt AS Expiring_Amt,
det.ordd_mn_billed_amt AS Expiring_Amt2
FROM
ccmast_restore_20201021.dbo.lti_orddet det
WHERE
det.ordd_mn_end_date IN (SELECT MAX(det.ordd_mn_end_date)
FROM ccmast_restore_20201021.dbo.lti_orddet det
GROUP BY det.ordd_ContractItemID)
AND det.ordd_ContractItemID IN (8198)
ORDER BY
det.ordd_mn_end_date DESC
Комментарии:
1. Можете ли вы уточнить? Что вы пытаетесь сделать?
2. Какая версия sql server?
3.Посмотрите на row_number; с
order by
order date desc
, а затемselect
на строки 1 и 2
Ответ №1:
Вы можете сделать это с помощью оконных функций LAG() и ROW_NUMBER():
SELECT ContractID, ordd_mn_end_date, Expiring_Amt, Expiring_Amt2
FROM (
SELECT ContractID,
ordd_mn_end_date,
ord_mn_billed_amt Expiring_Amt,
LAG(ord_mn_billed_amt) OVER (PARTITION BY ContractID ORDER BY ordd_mn_end_date) Expiring_Amt2,
ROW_NUMBER() OVER (PARTITION BY ContractID ORDER BY ordd_mn_end_date DESC) rn
FROM lti_orddet
WHERE ContractID IN (8198)
) t
WHERE rn = 1
Если вас интересует только 1 ContractID
, как ваш запрос, то вы можете удалить PARTITION BY ContractID
из обоих окон функции.
Смотрите демонстрацию.
Результаты:
ContractID | ordd_mn_end_date | Expiring_Amt | Expiring_Amt2 |
---|---|---|---|
8198 | 2021-10-31 | 2574.43 | 833.15 |
Ответ №2:
Я бы использовал LEAD()
или LAG()
для добавления следующего или предыдущего значения ordd_mn_billed_amt
, а затем использовал ROW_NUMBER()
, чтобы всегда выбирать первую строку…
WITH
lti_orddet_augmented AS
(
SELECT
lti_orddet.*,
LEAD(ord_mn_billed_amt)
OVER (PARTITION BY ordd_ContractItemID
ORDER BY ordd_mn_end_date DESC
)
AS ord_mn_billed_amt_previous,
ROW_NUMBER()
OVER (PARTITION BY ordd_ContractItemID
ORDER BY ordd_mn_end_date DESC
)
AS ordd_ContractItemID_RowNum
FROM
ccmast_restore_20201021.dbo.lti_orddet
)
SELECT
*
FROM
lti_orddet_augmented
WHERE
ordd_ContractItemID_RowNum = 1
AND ordd_ContractItemID = 8198
В этом случае я использовал LEAD()
так, чтобы окно для обеих функций было в том же порядке.
Комментарии:
1. Я использовал первый запрос, потому что это будет добавлено к существующему запросу. Это сработало отлично. Большое вам спасибо!