9

我正在创建两个表的连接视图,但是从 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。
我接近了以下代码(约 0.5 秒),但“不同”仅在所有列重复时过滤掉记录(而不仅仅是 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 OR id1/P5/AB5)

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

4

3 回答 3

14

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

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
于 2013-01-30T22:41:57.300 回答
3

您的原始查询正在为两列生成任意值(使用topwith no 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

此版本将 替换distinctgroup 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 或更高版本。

于 2013-01-30T22:32:03.860 回答
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和相同的查询将为您提供所需的结果。

已编辑

这种构造性能很好,不需要使用子查询。

于 2013-01-30T22:51:37.340 回答