Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/25.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查询是否可以在分页后加入?_Sql_Sql Server - Fatal编程技术网

SQL查询是否可以在分页后加入?

SQL查询是否可以在分页后加入?,sql,sql-server,Sql,Sql Server,我有一个简单的查询,如下所示,用于检索企业及其所有联系人 SELECT * FROM Business as business JOIN Contact as contact ON contact.BusinessEntityId = business.Id WHERE business.Id = '12345' 现在,我想做如下事情: SELECT * FROM Business as business JOIN Contact as contact

我有一个简单的查询,如下所示,用于检索企业及其所有联系人

SELECT  *
FROM Business as business
    JOIN Contact as contact
        ON contact.BusinessEntityId = business.Id
WHERE business.Id = '12345'
现在,我想做如下事情:

SELECT  *
FROM Business as business
    JOIN Contact as contact
        ON contact.BusinessEntityId = business.Id
WHERE business.State = 'TX'
ORDER BY business.Id
OFFSET 0 ROWS FETCH NEXT 20 ROWS ONLY
问题是分页发生在从整个查询返回的行上,这意味着我可能会在页面上获得最后一个业务联系人的部分结果。我想要的是对WHERE的结果进行分页,然后将这些结果与contacts连接起来。这样我就可以在页面上显示每家企业的所有联系信息


有没有办法不执行单独的查询来获取每个业务的联系人就可以做到这一点?

我认为临时表是最简单的方法

SELECT  *
INTO #temp
FROM Business as business
WHERE business.State = 'TX'
ORDER BY business.Id
OFFSET 0 ROWS FETCH NEXT 20 ROWS ONLY


SELECT *
FROM #temp as business
JOIN Contact as contact
   ON contact.BusinessEntityId = business.Id

这也会使它运行得非常快,因为加入只会发生在20条记录上。这还假设每个业务只有一个联系人,否则在第二次加入时将获得20条以上的记录,并且还必须在那里运行偏移/提取

这将通过
with TIES
子句完成,但SQL Server不支持它:

OFFSET 0 ROWS FETCH NEXT 20 ROWS WITH TIES;
但是您可以使用
densite\u-RANK
自己进行分页:

SELECT *
FROM
(
  SELECT b.*, c.*, DENSE_RANK() OVER (ORDER BY b.id) AS rn
  FROM business b
  JOIN contact c ON c.businessentityid = b.id
  WHERE b.state = 'TX'
) ranked
WHERE rn BETWEEN 101 AND 120;

这将跳过前100个ID,并给出接下来的20个ID,无论每个ID有多少行。

Alex的回答几乎完全符合我的需要。谢谢你,亚历克斯,这给了我达成最终解决方案所需要的东西。我已经将您的帖子标记为解决方案,但我认为将来阅读本文的任何人都会希望使用最终解决方案,因为它返回我需要的确切结果,它更简单,而且性能更好。所以,在这里

注:当我写这篇文章时,我还没有看过Thorsten post

为了使用临时表获得正确的结果,我必须使用
左连接
,因为有些公司没有联系人。仅使用
JOIN
会导致丢失业务记录。而且,可能应该在最后放下桌子。这是上述查询的工作版本

SELECT * INTO #temp
FROM Business AS business
WHERE business.State = 'TX'
ORDER BY business.Id
OFFSET 0 ROWS FETCH NEXT 20 ROWS ONLY

SELECT *
FROM #temp AS business
LEFT JOIN Contact AS contact ON contact.Id = business.Id

DROP TABLE #temp
这是可行的,但效果很差。经过一点研究,我意识到这可以通过嵌套查询来完成。这是我将使用的修改后的查询

SELECT *
FROM
  (SELECT *
   FROM Business AS business
   WHERE business.State = 'TX'
   ORDER BY business.Id
   OFFSET 0 ROWS FETCH NEXT 20 ROWS ONLY) AS business
LEFT JOIN Contact AS contact ON contact.Id = business.Id

您可以将
偏移量
放入子查询中。不过,我不确定你是否会在性能上获得特别优势;有时每个业务ID有多个联系人,OP希望确保只获得完整的联系人集。在我看来,你提供了一个很好的解决方案。这是有道理的,但我无法让它工作,我在最后的WHERE上得到了一个语法错误:关键字WHERE附近的语法不正确。需要AS、ID或引用的ID。我认为rn在那里不可用?可以使用了。首先似乎需要一个AS后的外部FROM。第二,我的表中有重复的列,所以我必须给它们加别名。因为需要给列加别名,这是一个很好的方法,但使用起来比较困难,但它的性能似乎要好一些。有人对这种方法与嵌套select的性能有意见吗?很抱歉,派生表(又称子查询)缺少别名。至于表现:我不知道。对我来说这似乎不快,但分页从来都不快。在给定的示例中,DBMS必须找到前120个ID才能得到最后20个ID。它可能会为此使用一些复杂的方法,但也可能只是对表中的每一行进行排序和排序。每次使用下一个范围调用查询时,它都会这样做。如果需要速度,可能需要为此创建一个索引列(或单独的表),并在开始页面读取表之前对页面组进行一次评估。