The following solution is non-recursive and can provide better performance:
DECLARE @Payment TABLE (
ID INT IDENTITY(1,1) PRIMARY KEY,
Location VARCHAR(50) NOT NULL,
PayID INT NOT NULL,
[Year] SMALLINT NOT NULL
);
INSERT @Payment
SELECT 'Loc1', 100, 2010
UNION ALL SELECT 'Loc1', 100, 2011
UNION ALL SELECT 'Loc1', 101, 2012
UNION ALL SELECT 'Loc2', 200, 2010
UNION ALL SELECT 'Loc2', 201, 2011
UNION ALL SELECT 'Loc2', 202, 2012
SELECT z.Location, z.GroupID,
MAX(CASE WHEN z.RowType = 1 THEN z.[Year] END) AS CurrentYear,
MAX(CASE WHEN z.RowType = 0 THEN z.[Year] END) AS PreviousYear,
MAX(CASE WHEN z.RowType = 1 THEN z.[PayID] END) AS CurrentPayID,
MAX(CASE WHEN z.RowType = 0 THEN z.[PayID] END) AS PreviousPayID
FROM
(
SELECT y.PayID, y.[Location], y.[Year],
(ROW_NUMBER() OVER(PARTITION BY y.Location ORDER BY y.RowNum + n.Num ASC) + 1) / 2 AS GroupID,
ROW_NUMBER() OVER(PARTITION BY y.Location ORDER BY y.RowNum + n.Num ASC) % 2 AS RowType
FROM
(
SELECT x.Location, x.[Year], x.PayID, ROW_NUMBER() OVER(PARTITION BY x.Location ORDER BY x.[Year] DESC) RowNum
FROM @Payment x
) y
INNER JOIN (VALUES (1), (2)) n(Num) ON y.RowNum = 1 AND n.Num = 1 OR y.RowNum > 1
) z
GROUP BY z.Location, z.GroupID
HAVING MAX(CASE WHEN z.RowType = 1 THEN z.[Year] END) = MAX(CASE WHEN z.RowType = 0 THEN z.[Year] END) + 1
AND MAX(CASE WHEN z.RowType = 1 THEN z.[PayID] END) <> MAX(CASE WHEN z.RowType = 0 THEN z.[PayID] END)
ORDER BY z.Location;
Output:
Location GroupID CurrentYear PreviousYear CurrentPayID PreviousPayID
--------- ------- ----------- ------------ ------------ -------------
Loc1 1 2012 2011 101 100
Loc2 1 2012 2011 202 201
Loc2 2 2011 2010 201 200
source
share