SQL - 从左连接中删除重复项

时间:2013-01-30 22:24:25

标签: sql sql-server join

我正在创建两个表的连接视图,但是从table2获得了不需要的重复项 例如:table1有9000条记录,我需要生成的视图包含完全相同的内容; table2可能有多个具有相同FKID的记录,但我只想返回一条记录(随机选择对我的客户来说是好的)。我有以下代码可以正常工作,但性能比预期慢(超过14秒)。

SELECT     
    OBJECTID
    , PKID
    ,(SELECT TOP (1) SUBDIVISIO
        FROM dbo.table2 AS t2
        WHERE (t1.PKID = t2.FKID)) AS ProjectName
    ,(SELECT TOP (1) ASBUILT1
        FROM dbo.table2 AS t2
        WHERE (t1.PKID = t2.FKID)) AS Asbuilt
FROM dbo.table1 AS t1

有没有办法与联接做类似的事情以加快表现? 我正在使用SQL Server 2008 R2 我接近以下代码(约.5秒),但'Distinct'仅在所有列重复时过滤掉记录(而不仅仅是FKID)。

SELECT
    t1.OBJECTID
    ,t1.PKID
    ,t2.ProjectName
    ,t2.Asbuilt
FROM dbo.table1 AS t1
    LEFT JOIN (SELECT
        DISTINCT FKID
        ,ProjectName
        ,Asbuilt
        FROM dbo.table2) t2
    ON t1.PKID = t2.FKID

表格示例

table1          table2

OID, PKID       FKID, ProjectName, Asbuilt
1, id1          id1, P1, AB1
2, id2          id1, P5, AB5
3, id4          id2, P10, AB2
5, id5          id5, P4, AB4

在上面的示例中,返回的记录应为id5 / P4 / AB4,id2 / P10 / AB2和(id1 / P1 / AB1或id1 / P5 / AB5)

我的搜索提出了类似的问题,但没有解决我的问题。 linklink
在此先感谢您的帮助。这是我的第一篇文章,如果我违反任何规则,请告诉我。

3 个答案:

答案 0 :(得分:13)

这将给出您所要求的结果,并且应该具有最佳性能。

SELECT     
    OBJECTID
    , PKID
    , t2.SUBDIVISIO,
    , t2.ASBUILT1

FROM        dbo.table1 AS t1
OUTER APPLY (
    SELECT  TOP 1 *
    FROM    dbo.table2 AS t2
    WHERE   t1.PKID = t2.FKID
    ) AS t2

答案 1 :(得分:3)

您的原始查询为两列生成任意值(使用top而不使用order by)。你可以用这个效果:

SELECT t1.OBJECTID, t1.PKID, t2.ProjectName, t2.Asbuilt
FROM dbo.table1 t1 LEFT JOIN
     (SELECT FKID, min(ProjectName) as ProjectName, MIN(asBuilt) as AsBuilt
      FROM dbo.table2
      group by fkid
     ) t2
    ON t1.PKID = t2.FKID

此版本将distinct替换为group by

要在SQL Server中获得一个真正随机的行(您的语法建议您使用它),请尝试以下操作:

SELECT t1.OBJECTID, t1.PKID, t2.ProjectName, t2.Asbuilt
FROM dbo.table1 t1 LEFT JOIN
     (SELECT FKID, ProjectName, AsBuilt,
             ROW_NUMBER() over (PARTITION by fkid order by newid()) as seqnum
      FROM dbo.table2
     ) t2
    ON t1.PKID = t2.FKID and t2.seqnum = 1

这假设版本为2005或更高版本。

答案 2 :(得分:1)

如果您想要描述结果,则需要使用INNER JOIN,以下查询将满足您的需求:

SELECT
  t1.OID,
  t1.PKID,
  MAX(t2.ProjectName) AS ProjectName,
  MAX(t2.Asbuilt) AS Asbuilt
FROM table1 t1
JOIN table2 t2 ON t1.PKID = t2.FKID
GROUP BY
  t1.OID,
  t1.PKID

如果要查看左表( table1 )中的所有行是否在右表中有对,请使用LEFT JOIN,同样的查询将为您提供所需的结果。< / p>

<强> EDITED

这种结构具有良好的性能,您不需要使用子查询。