Sql server 单个查询中的多个分组信息

Sql server 单个查询中的多个分组信息,sql-server,azure,Sql Server,Azure,我有一个计划交易(计划日期和计划金额)的结果集,与实际交易(实际日期和实际金额)的列表相关联 我正在起诉SQLAzure 我需要得到的是,对于每个计划id,我需要知道: 计划的最后付款日期(即最大实际日期) 该笔付款的相应金额(即上述日期的实际金额) 上次付款的ID(实际交易ID) s计划的下一个付款日期(因此,实际日期为空的最小计划日期) 位于上面的下一笔付款的金额 以下是创建测试数据的代码: SET DATEFORMAT DMY DECLARE @tbl TABLE ( s

我有一个计划交易(计划日期和计划金额)的结果集,与实际交易(实际日期和实际金额)的列表相关联

我正在起诉SQLAzure

我需要得到的是,对于每个计划id,我需要知道:

计划的最后付款日期(即最大实际日期)

该笔付款的相应金额(即上述日期的实际金额)

上次付款的ID(实际交易ID)

s计划的下一个付款日期(因此,实际日期为空的最小计划日期)

位于上面的下一笔付款的金额

以下是创建测试数据的代码:

    SET DATEFORMAT DMY

DECLARE @tbl TABLE
(
    schedule_id INT NOT NULL,
    scheduled_date DATE NOT NULL,
    actual_date DATE NULL,
    scheduled_amount DECIMAL(16,2) NOT NULL,
    actual_amount DECIMAL(18,2) NULL,
    actual_tranaction_id INT NULL
)

INSERT INTO @tbl
SELECT 77, '2014-06-17', '2014-06-17',292.18, 292.18 ,1 UNION
SELECT 77, '2014-07-17', '2014-07-17',292.18, 292.18 ,2 UNION
SELECT 77, '2014-08-17', '2014-08-17',292.18, 292.18 ,3 UNION
SELECT 77, '2014-09-17', '2014-09-17',292.18, 292.18 ,4 UNION
SELECT 77, '2014-10-17', '2014-10-17',292.18, 292.18 ,5 UNION
SELECT 77, '2014-11-17', '2014-11-17',292.18, 292.18 ,6 UNION
SELECT 77, '2015-02-17', '2015-02-18',504.00, 504.00 ,7 UNION
SELECT 77, '2015-03-17', NULL,504.00, NULL, NULL UNION
SELECT 77, '2015-04-17', NULL,504.00, NULL, NULL UNION
SELECT 77, '2015-05-17', NULL,504.00, NULL, NULL UNION
SELECT 77, '2015-06-17', NULL,504.00, NULL, NULL UNION
SELECT 77, '2015-07-17', NULL,504.00, NULL, NULL UNION
SELECT 77, '2015-08-17', NULL,504.00, NULL, NULL UNION
SELECT 77, '2015-09-17', NULL,504.00, NULL, NULL UNION
SELECT 77, '2015-10-17', NULL,504.00, NULL, NULL UNION
SELECT 77, '2015-11-17', NULL,504.00, NULL, NULL UNION
SELECT 77, '2015-12-17', NULL,504.00, NULL, NULL UNION
SELECT 92, '2014-06-17', '2014-06-17',700.00, 700.00,10 UNION
SELECT 92, '2014-07-17', '2014-07-17',550.00, 700.00, 11 UNION
SELECT 92, '2014-08-17', '2014-08-17',700.00, 700.00, 12 UNION
SELECT 92, '2014-09-17', '2014-09-17',700.00, 700.00, 13 UNION
SELECT 92, '2014-10-17', '2014-10-16',620.00, 580.00, 14 UNION
SELECT 92, '2014-11-17', '2014-11-14',600.00, 601.00, 15 UNION
SELECT 92, '2014-12-17', '2014-12-17',700.00, 702.00, 16 UNION
SELECT 92, '2015-01-17', '2015-01-17',850.00, 851.00, 17 UNION
SELECT 92, '2015-02-17', '2015-02-17',850.00, 853.00, 18 UNION
SELECT 92, '2015-03-17', NULL,850.00, NULL, NULL UNION
SELECT 92, '2015-04-17', NULL,850.00, NULL, NULL UNION
SELECT 92, '2015-05-17', NULL,850.00, NULL, NULL UNION
SELECT 92, '2015-06-17', NULL,850.00, NULL, NULL UNION
SELECT 92, '2015-07-17', NULL,850.00, NULL, NULL UNION
SELECT 92, '2015-08-17', NULL,850.00, NULL, NULL UNION
SELECT 92, '2015-09-17', NULL,850.00, NULL, NULL UNION
SELECT 92, '2015-10-17', NULL,850.00, NULL, NULL UNION
SELECT 92, '2015-11-17', NULL,850.00, NULL, NULL UNION
SELECT 92, '2015-12-17', NULL,850.00, NULL, NULL UNION
SELECT 92, '2016-01-17', NULL,850.00, NULL, NULL UNION
SELECT 92, '2016-02-17', NULL,850.00, NULL, NULL UNION
SELECT 92, '2016-03-17', NULL,850.00, NULL, NULL

SELECT * FROM @tbl
在这种情况下,预期结果将是两行:

scheduleId, lastPaymentDate, lastPaymentAmount, nextPaymentDate, nextPaymentAmount 
77, 2015-02-18, 504.00, 2015-03-17, 504.00 
92, 2015-02-17, 853.00, 2015-03-17, 850.00

在一个高效的查询中以某种方式做到这一点,这是可能的吗?还是需要将其分解为多个查询,并有自己的位置和分组?

这是一种方法:

SELECT
  t.schedule_id,
  a.actual_date,
  a.actual_amount,
  s.scheduled_date,
  s.scheduled_amount
FROM (
    select 
      distinct schedule_id
    from 
      tbl
  ) t
  outer apply (
    select top 1
      actual_date,
      actual_amount
    from
      tbl a
    where
      a.schedule_id = t.schedule_id and
      a.actual_date is not null
    order by
      actual_date desc) a
  outer apply (
    select top 1
      scheduled_date,
      scheduled_amount
    from
      tbl s
    where
      s.schedule_id = t.schedule_id and
      s.scheduled_date > getdate()
    order by
      scheduled_date asc) s

派生表获取id,两个外部应用程序获取前1名的实际金额和计划金额。

尝试以下语句:

;WITH    cte
          AS ( SELECT   * ,
                        ROW_NUMBER() OVER ( PARTITION BY schedule_id ORDER BY actual_date DESC, scheduled_date DESC ) AS rn1 ,
                        ROW_NUMBER() OVER ( PARTITION BY schedule_id ORDER BY actual_date , scheduled_date ) AS rn2
               FROM     @tbl
             )
    SELECT  c1.schedule_id ,
            c2.actual_date ,
            c2.actual_amount ,
            c1.scheduled_date ,
            c1.scheduled_amount
    FROM    cte c1
            JOIN cte c2 ON c1.rn1 = c2.rn2
    WHERE   ( c1.rn1 = 1
              OR c1.rn2 = 1
            )
            AND c2.rn1 = 1
输出:

schedule_id   actual_date     actual_amount   scheduled_date    scheduled_amount
77            2015-02-18      504.00          2015-03-17        504.00
92            2015-02-17      853.00          2015-03-17        850.00

那就对了!谢谢@JamesZ