【问题标题】:INNER JOIN with a large tableINNER JOIN 与大表
【发布时间】:2017-08-31 12:02:01
【问题描述】:

我目前正在使用 Microsoft Access 2013,我正在尝试将 Table1 和 Table2 连接在一起,但问题是 Table2 很大。表 1 是零件、供应商组合的列表,其中 PK 作为零件、供应商。表 2 是我创建的表,其中包含每个部分、供应商组合的前 2 个最新报价。所有这些报价都是从带有 PK quote_id 的表中提取的。我认为我创建 Table2 可能是问题所在,因为我无法使用每个部分、供应商组合创建 Table2(我必须按供应商过滤掉)。这是我用于 Table2 的查询。

a.part, a.vendor, a.quote_date
FROM quoteTable AS a 
WHERE a.quote_date > DATEADD("yyyy", -3, DATE()) AND 
a.quote_date IN 
 (SELECT TOP 2 quote_date 
 FROM quoteTable 
 WHERE quote_date > DATEADD("yyyy", -3, DATE()) AND 
 part=a.part  AND vendor=a.vendor 
 ORDER BY quote_date DESC)

如果有人知道一种更好的方法,可以从表格中为每个零件、供应商组合选择前 2 个最新报价,我将不胜感激。至于加入,这可行,但需要的时间太长。

SELECT *
FROM Table1 AS a INNER JOIN Table2 AS b ON a.id = b.id

我想知道是否有一种方法可以使用 Table1 中的 id 来过滤 Table2?像这样的:

SELECT * 
FROM Table1 AS a INNER JOIN
   (SELECT * FROM Table2 WHERE id=a.id) AS b ON a.id = b.id

【问题讨论】:

  • 你为你的表创建索引了吗?
  • 好吧,如果您选择海量数据,则需要很长时间。你真的需要所有的记录吗?
  • 性能问题应该包括EXPLAIN ANALYZE和一些关于表大小、索引、当前时间性能、期望时间等的信息。Slow是一个相对术语,我们需要一个真实的值来比较。
  • 是什么让表 2 如此庞大。里面有图片吗?
  • 我需要表1中的所有记录,但我只需要表1中存在的表2中的记录。它有点复杂。所以表 2 是我创建的表,其中填充了引用表中每个部分的前 2 个最新引用。当我将表 1 与报价表连接起来时,即使有 1 亿个报价,它也会运行得很快。但是当我加入表 2 时需要几个小时

标签: sql join


【解决方案1】:

真正的解决方案是您需要 TABLE2.id 上的索引。我假设它不是该表的主键,因为它可能是 TABLE1 的主键,为什么会有两个表具有完全相同的匹配主键?它不会是一个规范化的布局。但话又说回来,有时去规范化是有意义的。

【讨论】:

  • “为什么你会有两个具有完全相同的匹配主键的表”——也许是因为它们模拟了相同的现实生活实体?例如TABLE1 模型书籍,TABLE2 模型非小说书籍,id 模型 ISBN 在两个表中,并且 OP 的命名约定很差。
  • “它不会是一个规范化的布局” - 如果您认为表格没有完全规范化,请注意说明您认为它们当前处于何种正常形式以及如何修复设计以使其完全归一化?
  • table1 的 PK 是供应商的一部分。 table2 的 PK 是 quote_id,但我部分加入了这些表,供应商。基本上,table1 是零件列表,而 table2 是每个零件的前 2 个最新报价的列表。抱歉不清楚,我更新问题
  • 正如我所怀疑的,表 2 中的“id”(实际上是供应商的一部分)不是主键。因此,它可能未编入索引 - Access 中的主键会自动编入索引,但除非您明确这样做,否则这些属性不会被编入索引。您的问题的解决方案是您的报价表需要在(部分,供应商)上有一个索引。如果还没有,添加该索引将大大提高您的查询速度。
【解决方案2】:

你绝对可以使用:

SELECT * 
FROM Table1 AS a 
INNER JOIN
(SELECT * FROM Table2 WHERE id=a.id) AS b 
ON a.id = b.id

或者你可以使用:

With CTE
as
(
SELECT * 
FROM Table2 
WHERE id in (select id from table1)
)
SELECT * 
FROM Table1 AS a 
INNER JOIN
CTE 
ON CTE.Id = a.Id

对于性能问题,您可以尝试在两个表的id 列上创建索引,或者尝试从结果中限制所选列。

【讨论】:

  • 在另一个选择内有一个选择,尤其是在一个 IN 子句中,是非常糟糕的 SQL。您几乎可以打赌,只有 SELECT * FROM TABLE 2 where id in (select id from table 1) 是您可以编写的最差的、性能方面的。
  • @AgapwIesu 偶然看到一篇文章说IN在某些情况下性能很好,尤其是在比较值时优于Join
  • 当你有一个像我在评论中强调的那样的声明时,不,你不会有好的表现。即使使用索引,这也比他的连接差得多。 IN 子句通常只有在您可以提供离散值列表而不是来自另一个表的 select 语句时才能获得更好的性能。
  • 此外,Access 甚至还做 CTE 吗?不是最后一次听说。
猜你喜欢
  • 1970-01-01
  • 2014-02-21
  • 1970-01-01
  • 1970-01-01
  • 2012-02-16
  • 2013-07-19
  • 2021-10-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多