左连接一行

时间:2014-06-05 11:26:01

标签: sql sql-server left-join

我有一个SQL Server查询,如下所示:

SELECT  ListingId, hh.DateAltered
FROM Listings (NOLOCK)
LEFT JOIN (
    SELECT 
        h.ParentId, 
        h.DateAltered 
    FROM 
        History AS h
    WHERE h.ParentType = 'Listing' 
) hh 
ON hh.ParentId = Listings.ListingId
WHERE ListingId = 56082

所以基本上我有两个表,ListingsHistoryListings表只有1行。 History表有5行链接到Listings表记录(从LEFT JOIN可以看出)。

当我运行上面的查询时,它返回5行。这是因为History表有5行链接到Listings表中的1行。

ListingId   DateAltered
56082   2013-11-06 09:27:29.647
56082   2013-11-08 14:30:42.543
56082   2013-11-08 15:11:30.390
56082   2013-11-14 09:54:21.060
56082   2014-01-09 16:23:52.440

但是我只需要History表中的一行,所以我可以看到最后一个DateAltered是什么。

所以我认为就像在TOP(1)查询中添加LEFT JOIN一样简单:

SELECT  ListingId, hh.DateAltered
FROM Listings (NOLOCK)
LEFT JOIN (
    SELECT TOP(1)
        h.ParentId, 
        h.DateAltered 
    FROM 
        History AS h
    WHERE h.ParentType = 'Listing' 
) hh 
ON hh.ParentId = Listings.ListingId
WHERE ListingId = 56082

现在确实返回1行(这就是我想要的),但现在DateAltered列是NULL

ListingId   DateAltered
56082           NULL

为什么会这样?我该如何解决这个问题?

4 个答案:

答案 0 :(得分:2)

这种情况正在发生,因为您选择的top 1记录与您的列表表格的ID不同。

您想要ID与历史记录表中的最新记录匹配。您可以使用row_number

来获取此信息
SELECT  ListingId, hh.DateAltered
FROM Listings (NOLOCK)
LEFT JOIN (
    select * 
    from 
    (
        SELECT 
            h.ParentId, 
            h.DateAltered,
            ROW_NUMBER() over (partition by parentid order by datealtered desc) rn
        FROM 
            History AS h
        WHERE h.ParentType = 'Listing' 
    ) h
    where rn=1
) hh 
ON hh.ParentId = Listings.ListingId
WHERE ListingId = 56082

答案 1 :(得分:1)

如果您想要上一个DateAltered值,则应使用MAXGROUP BY

SELECT  ListingId, hh.DateAltered
FROM Listings (NOLOCK)
LEFT JOIN (
    SELECT 
        h.ParentId, 
        MAX(h.DateAltered) AS DateAltered
    FROM 
        History AS h
    WHERE h.ParentType = 'Listing' 
    GROUP BY h.ParentId
) hh 
ON hh.ParentId = Listings.ListingId
WHERE ListingId = 56082

答案 2 :(得分:0)

您只加入历史记录中的一行,您不知道它是否具有匹配的parentid。你可以将top(1)放在主查询中,并按日期排序。

SELECT TOP(1) ListingId, hh.DateAltered
FROM Listings (NOLOCK)
LEFT JOIN (
    SELECT 
        h.ParentId, 
        h.DateAltered 
    FROM 
        History AS h
    WHERE h.ParentType = 'Listing' 
) hh 
ON hh.ParentId = Listings.ListingId
WHERE ListingId = 56082
order by hh.DateAltered desc

然而我的建议是这样做:

SELECT l.ListingId
     , max(hh.DateAltered) as DateAltered
  FROM Listings (NOLOCK) l
  left join
       History AS hh
    ON hh.ParentId = l.ListingId
   and hh.ParentType = 'Listing'
 WHERE l.ListingId = 56082
 group by
       l.ListingId

为每个listingid提供最大日期更改。

答案 3 :(得分:0)

您需要使用子查询并将值作为列返回

之类的东西
SELECT  ListingId, 
        (SELECT max(h.DateAltered) 
         FROM  History AS h
         WHERE h.ParentId = Listings.ListingId
                and h.ParentType = 'Listing') as LatestDateAltered

FROM Listings (NOLOCK)
WHERE ListingId = 56082