Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql &引用;选择前10名,然后加入表格“;,而不是",;从关联表中选择前10名“;_Sql_Sql Server_Stored Procedures - Fatal编程技术网

Sql &引用;选择前10名,然后加入表格“;,而不是",;从关联表中选择前10名“;

Sql &引用;选择前10名,然后加入表格“;,而不是",;从关联表中选择前10名“;,sql,sql-server,stored-procedures,Sql,Sql Server,Stored Procedures,我继承了一个存储过程,它跨八个表执行联接,其中一些表包含数十万行,然后从联接结果中选择前十个条目 在过程开始时,我有足够的信息从一个表中选择这十行,然后在这十行上执行这些连接,而不是在成千上万的中间行上执行这些连接 如何选择前十行,然后只对这十行执行联接,而不是对表中的所有数千行执行联接?我应该尝试: SELECT * FROM (SELECT TOP 10 * FROM your_table ORDER BY your_condition) p INNER JOIN seco

我继承了一个存储过程,它跨八个表执行联接,其中一些表包含数十万行,然后从联接结果中选择前十个条目

在过程开始时,我有足够的信息从一个表中选择这十行,然后在这十行上执行这些连接,而不是在成千上万的中间行上执行这些连接

如何选择前十行,然后只对这十行执行联接,而不是对表中的所有数千行执行联接?

我应该尝试:

SELECT * FROM
    (SELECT TOP 10 * FROM your_table
     ORDER BY your_condition) p
INNER JOIN second_table t
    ON p.field = t.field

您还可以使用CTE定义顶部X,然后使用它

例如,这仅限于前40个标记

with top40 as (
  select top 40 t.id, t.tagname
  from tags t, posttags pt
  where pt.tagid = t.id
  group by t.tagname, t.id
  order by count(pt.postid) desc
),

myanswers as(
  select p.parentid, p.score
  from posts p
  where
    p.owneruserid = ##UserID## and
    p.communityowneddate is null
)

select t40.tagname as 'Tag', sum(p1.score) as 'Score',
case when sum(p1.score) >= 15 then ':-)' else ':-(' end as 'Status'
from top40 t40, myanswers p1, posttags pt1
where
  pt1.postid = p1.parentid and
  pt1.tagid = t40.id
group by t40.tagname
order by sum(p1.score) desc
  • 如果有内部联接,优化器可能无法首先执行前10项,因为它无法确保内部联接以后不会排除行。如果它从主表中选择了10行,但由于连接,最后只返回了7行,这将是一个错误。由于这个原因,使用Marco的重写可能会提高性能,因为您明确表示在连接之前限制行是安全的
  • 如果您的查询足够复杂,查询计划优化器可能无法找到一个好的计划。它只需要几百毫秒,即使有几个连接,也可能有数千种不同的方式执行查询(不同的连接顺序,等等)。如果是这种情况,您将受益于先将前10行存储在临时表中,然后像下面这样使用它:

    select top 10 *
    into #MainResults
    from MyTable
    order by your_condition;
    
    
    select *
    from #MainResults r
    join othertable t
      on t.whatever = r.whatever;
    
    我见过第二种方法产生巨大影响的案例


  • 通常,优化器就是这样做的。检查执行计划-这里可能没有问题。查询返回用户处理过的最后十条记录。这个问题被曝光是因为处理过最多记录的用户看到的问题最严重。我承认我可能是错误地看待了这个问题,但它肯定不是一个非问题啊,比如。。。所有的独立唱片都在吗?只是想确认一下,问题肯定是最近的十张专辑选得太晚了,在加入数千行之后选择了前十名。前10名现在在子查询中被选中(由Marco解决),然后执行更少的连接;CTE只是嵌套子查询的一种更优雅的语法。(有一些例外,但在这种情况下是真的)。嗯,我几乎总是有相反的经历。将临时表移动到内联视图、CTE或普通旧联接中比临时表做得更好—这完全取决于规模。如果行数很小(在本例中为10),则可能值得。如果他们开始变得更高,那就不值得了。