LEFT OUTER JOIN(SELECT*FROM TABLE)可能吗?

Bon*_*Kun 5 t-sql sql-server

我有两个表PersonSalary.

Person:

PersonId   |  Name   |   Surname
--------------------------------
       1      John          Deer
       2      Mark          Bear
Run Code Online (Sandbox Code Playgroud)

Salary:

SId | PersonId | Date                       | Salary
----------------------------------------------------
1            2   2013-01-01 00:00:00.000      100
2            2   2012-01-01 00:00:00.000      90
3            2   2011-01-01 00:00:00.000      80
Run Code Online (Sandbox Code Playgroud)

我想要做的是,如果一个人有工资记录,那么它应该在结果中显示最新的工资信息,如果没有工资记录那么它应该显示工资信息为null,这就像...

Result
------------------------------------------------------------------------
PersonId   |   Name   | Surname  |  Date                      |  Salary
       1       John        Deer     NULL                            NULL
       2       Mark        Bear     2013-01-01 00:00:00.000         100
Run Code Online (Sandbox Code Playgroud)

我知道它必须是这样的,但由于缺乏知识,我无法实现......

SELECT 
    P.PersonId, P.Name, P.Surname, SL.Date, SL.Salary
FROM 
    PERSON P
LEFT OUTER JOIN 
    (SELECT TOP 1 S.PersonId, S.Date, S.Salary 
     FROM Salary 
     WHERE S.PersonId = P.PersonId ORDER BY Date DESC) SL
Run Code Online (Sandbox Code Playgroud)

Cᴏʀ*_*ᴏʀʏ 4

我首先会根据人员和日期、CTE 和职能对工资进行排名ROW_NUMBER()。这会将人员最近的工资按降序排列在第一个位置,我们可以稍后进行过滤(其中排名 = 1)。之后,它就变成了别名 CTE 的简单LEFT JOINfrom :Person

WITH RankedSalaries AS
(
    SELECT 
        PersonId
        ,Date
        ,Salary
        ,ROW_NUMBER() OVER (PARTITION BY PersonId ORDER BY Date DESC) AS RowNum
    FROM 
        Salary
)
SELECT 
    p.PersonId
    ,p.Name
    ,p.Surname
    ,s.Date
    ,s.Salary
FROM
    Person p
LEFT JOIN
    RankedSalaries s
    ON
    p.PersonId = s.PersonId
WHERE
    s.RowNum = 1
Run Code Online (Sandbox Code Playgroud)

或者,您可以获取 CTE 的内容并将其移到您开始的查询的括号之间(即LEFT JOIN (<CTE query>))。只需记住添加= 1约束即可。