获取包括NULL的最新记录

时间:2017-03-16 22:26:56

标签: sql sql-server

我在MS SQL Server中有两个表

一个包含有关用户的信息

TBL_USER

UserID| Name         | Mail      |...many columns...|
------+--------------+---------- +------------------+
  292 | John Smith   | @@@@@@@@  |  ...             |
  293 | Anna Bennet  | @@@@@@@@  |  ...             |
  294 | Mark Johnson | @@@@@@@@  |  ...             |

其他表格是每个用户付款的注册表,其中UserID作为我的TBL_USER表格的外键

TBL_PAYMENT

UserID| PaymentID | Amount | PaymentDate |
------+-----------+----------------------+
  292 |    782    |   378  | 02-17-2016  |
  293 |    783    |   172  | 03-22-2016  |
  292 |    784    |   395  | 03-28-2016  |
  292 |    785    |   358  | 04-01-2016  |
  293 |    786    |   826  | 05-07-2016  |
  293 |    787    |   835  | 05-23-2016  |

我想要做的是一个查询语句或存储过程,当该用户没有像这样付款时,为每个用户和同一结果表中的最新付款带来一个表或null或任何其他静态值

UserID| Name         | PaymentID | Amount | PaymentDate |
------+--------------+---------- +--------+-------------+
  292 | John Smith   |    785    |  358   | 04-01-2016  |
  293 | Anna Bennet  |    786    |  786   | 05-07-2016  |
  294 | Mark Johnson |    NULL   |  NULL  |   NULL      |

现在我有以下声明,但这只给了我每个用户的最后一笔付款,只有他们完成了一次付款。我想在同一张表中找到遗失的报告。

SELECT
    usr.UserID,
    usr.UserName,
    pay.PaymentID,
    pay.Amount,
    pay.PaymentDate
FROM TBL_USER usr
    LEFT OUTER JOIN TBL_PAYMENT pay ON usr.UserID = pay.UserID
    INNER JOIN (
        SELECT UserID,MAX(PaymentDate) AS MAXDATE
        FROM TBL_PAYMENT Group by UserID
    ) latest ON pay.UserID = latest.UserID AND pay.PaymentDate = latest.MAXDATE

任何人都可以帮我解决这个问题吗?

3 个答案:

答案 0 :(得分:1)

使用窗口功能:

SELECT usr.UserID, usr.UserName,
       pay.PaymentID, pay.Amount, pay.PaymentDate
FROM TBL_USER usr LEFT OUTER JOIN
     (SELECT pay.*,
             ROW_NUMBER() OVER (PARTITION BY userId Order by PaymentDate DESC) as seqnum
      FROM TBL_PAYMENT pay
     ) pay
      ON usr.UserID = pay.UserID AND seqnum = 1;

答案 1 :(得分:0)

如果每个用户不重复PaymentDates,这应该可以正常工作

    SELECT 
TBL_USER.UserId, TBL_USER.Name, pm.PaymentId, pm.Amount, pm.PaymentDate
FROM TBL_USER 
LEFT JOIN (
    SELECT
    U.USERID,.MAX(P.PaymentDate) AS MAXDATE
    FROM TBL_USER U
    INNER JOIN TBL_PAYMENT P on U.UserID = P.UserID
    group by U.USERID
) J
on TBL_USER.UserID = J.UserID
LEFT JOIN TBL_PAYMENT Pm on Pm.PaymentDate = J.MAXDATE

答案 2 :(得分:0)

WITH子句更具可读性 - 并且包含测试数据:

WITH
-- input, don't use in real query
tbl_user(UserID,Name,Mail) AS (
          SELECT 292,'John Smith','@@@@@@@@'
UNION ALL SELECT 293,'Anna Bennet','@@@@@@@@'
UNION ALL SELECT 294,'Mark Johnson','@@@@@@@@'
)
,
tbl_payment(UserID,PaymentID,Amount,PaymentDate) AS (
          SELECT 292,782,378,DATE '2016-02-17'
UNION ALL SELECT 293,783,172,DATE '2016-03-22'
UNION ALL SELECT 292,784,395,DATE '2016-03-28'
UNION ALL SELECT 292,785,358,DATE '2016-04-01'
UNION ALL SELECT 293,786,826,DATE '2016-05-07'
UNION ALL SELECT 293,787,835,DATE '2016-05-23'
)
-- end of input - start real query with WITH,
-- not comma, here
, 
interesting_payments AS (
SELECT
  u.userid
, MAX(paymentdate) AS paymentdate
FROM tbl_user u
LEFT JOIN tbl_payment USING(userid)
GROUP BY u.userid
)
SELECT
  u.userid
, u.name
, p.paymentid
, p.amount
, p.paymentdate
FROM interesting_payments i
JOIN tbl_user u USING(userid)
LEFT JOIN tbl_payment p USING(userid,paymentdate)
;


userid|name        |paymentid|amount|paymentdate
   292|John Smith  |      785|   358|2016-04-01
   293|Anna Bennet |      787|   835|2016-05-23
   294|Mark Johnson|NULL     |NULL  |NULL