【问题标题】:TSQL Join to replace a unionTSQL Join 替换联合
【发布时间】:2015-05-04 01:35:03
【问题描述】:

我有两个类似于以下的表:

个人资料表

身份证 |服务标识 |访问权限 ---------------------------- 1 | 123 | 1 2 | 123 | 1 3 | 123 | 2

附加配置文件表(ProfileId 是 Profile.Id 的外键)

身份证 |个人资料 ID |访问权限 ---------------------------- 1 | 1 | 2 2 | 1 | 3 3 | 2 | 2 4 | 3 | 3

我目前有一个在这两个表上执行 UNION ALL 的视图,以便我可以查询它“ProfileId = 1”并获得以下结果集:

个人资料 ID |服务标识 |访问权限 ---------------------------------- 1 | 123 | 1 1 | 123 | 2 1 | 123 | 3

这似乎很慢。

所以,我想知道是否/如何使用单个查询获得相同的结果集,但我正在努力寻找一种方法。

任何帮助将不胜感激。

视图后面的查询:

SELECT Id, ServiceId, AccessLevel FROM Profile
UNION ALL
SELECT P.Id, P.ServiceId, A.AccessLevel
FROM Profile P
INNER JOIN AdditionalProfile A ON A.ProfileId = P.Id

每个表包含大约。 160,000 条记录。

【问题讨论】:

  • 需要FULL OUTER JOIN(如果任何表为空。)我猜UNION ALL 更好...你确定它很慢吗?!?
  • 如果您的查询速度较慢,请发布 QUERY 和 QUERY PLAN、记录数等。没有人可以根据提供的信息帮助您优化它。
  • 我已经从视图中添加了查询。
  • 您希望获得什么样的性能(就经过的时间而言),您会得到什么?此外,您希望在查询单个 ID 或所有 ID 时看到最佳性能?
  • 仅查看您的查询,我不明白您要做什么。那么,您想从Profile 表中选择所有行,然后从同一个Profile 表中选择同样在AdditionalProfile 中的记录,从而留下重复项?加快此速度的一种方法是让您的查询简单地SELECT p.Id, p.ServiceId, p.AccessLevel, a.Id FROM Profile P LEFT JOIN AdditionalProfile A on P.Id = A.ProfileId - 这将为您提供您正在寻找的相同数据,但结果集不同。第三列不是重复的,而是null 或不是。

标签: sql tsql join union union-all


【解决方案1】:
SELECT p1.Id, p1.ServiceId, COALESCE(p2.AccessLevel, p1.AccessLevel)
  FROM Profile p1
  left join AdditionalProfile p2
    on p2.ProfileId = p1.Id
   and p2.AccessLevel <> p1.AccessLevel 

可以使用 ISNULL 而不是 COALESCE

(正常)视图的问题是没有索引

最好把它做成一个存储过程
如果 Id 和 ProfileId 被编入索引,这将快速吸烟

SELECT p1.Id, p1.ServiceId, ISNULL(p2.AccessLevel, p1.AccessLevel)
  FROM Profile p1
  left join AdditionalProfile p2
    on p2.ProfileId = p1.Id
   and p2.AccessLevel <> p1.AccessLevel 
 where p1.ID = @ID 

好的试试

SELECT p1.Id, p1.ServiceId, COALESCE(p2.AccessLevel, p1.AccessLevel)
  FROM Profile p1
 outer join AdditionalProfile p2
    on p2.ProfileId = p1.Id

【讨论】:

  • 您好,感谢您的回复,但这不起作用。它只会返回 AdditionalProfile 表中的记录。
  • @kmcoulson 不,它不仅只返回 AdditionalProfile 记录。左连接返回左侧的所有行 - 这就是左连接的作用。
  • 对不起,再解释一下。我需要来自 Profile 的记录和来自 AdditionalProfile 的记录(即来自 Profile 的 1 行,来自 AdditionalProfile 的 2 行,总共 3 行)。您的建议只会从 AdditionalProfile 表中返回“AccessLevel”值,除非该表中不存在任何记录,否则它将从 Profile 中返回“AccessLevel”值。
  • 1) 性能不佳可能是由于该表之间缺少索引。 2)我想最好的方法是使用联合,但在选择过滤Id并且没有任何加入时。只需从 [Profile] where {filter} 中选择 union select from [AdditionalProfile] where {filter}
猜你喜欢
  • 1970-01-01
  • 2015-12-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-06
  • 1970-01-01
相关资源
最近更新 更多