仅选择具有MAX日期或NULL的行

时间:2014-06-04 20:10:54

标签: sql sql-server sql-server-2005

我需要一个查询,该查询将生成所有成员及其相应状态的非重复列表。国家(以及从其他表连接的一些其他数据)。每个成员可能有0多个MemberAddress记录。如果成员具有MemberAddress记录,我只想加入最近修改过的记录。如果该成员没有任何关联的MemberAddress记录,我仍然希望该成员显示在列表中,但状态和国家将是NULL值。

SELECT m.member, ma.state, ma.country FROM Member m
 LEFT OUTER JOIN MemberAddress ma ON m.member = ma.member           
 INNER JOIN (SELECT Member, MAX(Modified) AS MaxDate
        FROM MemberAddress
        GROUP BY Member) AS m2
    ON (ma.Member = m2.Member AND ma.Modified = m2.MaxDate)

此查询删除成员具有多个MemberAddress记录时导致的重复项,但不允许没有任何MemberAddress记录的成员。

如何更改此查询以显示没有任何MemberAddress记录的成员?

谢谢!

编辑添加:我正在使用SQL 2005

5 个答案:

答案 0 :(得分:1)

你的版本非常接近。您可以使用两个左连接来执行此操作:

SELECT m.member, ma.state, ma.country
FROM Member m LEFT OUTER JOIN
     MemberAddress ma
     ON m.member = ma.member LEFT OUTER JOIN
     (SELECT Member, MAX(Modified) AS MaxDate
      FROM MemberAddress
      GROUP BY Member
     ) m2
     ON (ma.Member = m2.Member AND ma.Modified = m2.MaxDate);

答案 1 :(得分:1)

你是在正确的轨道上,但是ma和m2之间的连接本身必须是一个完整的子查询。问题是你的INNER JOIN适用于整个查询,而不仅仅是ma和m2之间的关系:

SELECT m.member, mx.state, mx.country
FROM Member m
 LEFT OUTER JOIN (
SELECT ma.state, ma.country, ma.member from MemberAddress ma            
 INNER JOIN (SELECT Member, MAX(Modified) AS MaxDate
    FROM MemberAddress
    GROUP BY Member) AS m2
ON (ma.Member = m2.Member AND ma.Modified = m2.MaxDate)
) mx ON m.member = mx.member

假设我没有输入错误(除了括号,我修复了)。

答案 2 :(得分:0)

您可以尝试使用Row_Number获取具有最大日期的行:

SELECT 
     m.member
    ,ma.state
    ,ma.country
FROM Member m
LEFT OUTER JOIN (
    select
         *
        ,row_number() over(partition by Member order by modified desc) as dateOrder
    from MemberAddress
) ma 
    ON m.member = ma.member
    and ma.dateOrder = 1

我是从内存中编写这种语法,但我认为这样可行。

答案 3 :(得分:0)

下面的内容应该有效(未经测试)

SELECT member, state, country
FROM (
    SELECT m.member, ma.state, ma.country
         , row_number() over (partition by m.member
                          order by ma.Modified desc) as rn 
    FROM Member m
    LEFT JOIN MemberAddress ma 
        ON m.member = ma.member
) as T
WHERE rn = 1

答案 4 :(得分:0)

你已经非常接近了。这只需要INNER JOIN成为LEFT JOIN MemberMemberAddress之间的OVER。现在,内连接会导致行丢失。

包括SELECT DISTINCT m.member, ma.state, ma.country FROM Member m LEFT JOIN (SELECT Member, MAX(NVL(Modified, 0)) AS MaxDate, state, country FROM MemberAddress GROUP BY Member) ma ON m.member = ma.member 条款在内的答案也是完全合法的。有一个MSDN Article for more information on that approach.

更新:添加对我有用的查询:

{{1}}