Sql左或右联接一对多分页

时间:2019-04-07 19:38:09

标签: sql sql-server tsql

我有一个主表,并通过左外部或右外部外部联接来联接其他表。作为结果,主表的一行在联接查询中有30多个行。我尝试分页。但是问题是我不知道一个主表行结果将返回多少行。

示例:

主表的第一行结果在我的查询中有40行。 主表第二行结果是120行。

问题(问题)更新: 对于分页,我需要给pagesize选择结果的数量。但是我不知道选择结果的正确数量。例如,我给出的页面编号为1,页面大小为50,因此我无法获得正确的结果。我需要为我的主表前10个结果给出正确的页面大小。也许对于前10行,结果行数为200,但我的页面大小为50,这就是问题所在。

我正在使用Sql2014。我的ASP.NET项目需要它,但并不重要。

示例更新:

这就像搜索酒店进行预订。您的主表是酒店表。另外还有(可传播的)图像,(可传播的)视频,(可放置的)位置以及(可评论的)注释,它们多于一行,并且与酒店具有一对多的关系。对于一家酒店,所有信息的结果都将为100、50或10行。我想对这家酒店的结果进行分页。我需要始终获得20或30或50家酒店才能在我的项目中发挥作用。

示例查询更新:

   SELECT  
      *
   FROM
      KisiselCoach KC
         JOIN WorkPlace WP
            ON KC.KisiselCoachId = WP.WorkPlaceOwnerId
         JOIN Album A
            ON KC.KisiselCoachId = A.AlbumId
            JOIN Media M
               ON A.AlbumId = M.AlbumId
         LEFT JOIN Rating R
            ON KC.KisiselCoachId = R.OylananId 
         JOIN FrUser Fr
            ON KC.CoachId = Fr.UserId 
         JOIN UserJob UJ
            ON KC.KisiselCoachId = UJ.UserJobOwnerId 
            JOIN Job J
               ON UJ.JobId = J.JobId 
         JOIN UserExpertise UserEx
            ON KC.KisiselCoachId = UserEx.UserExpertiseOwnerId
            JOIN Expertise Ex
               ON UserEx.ExpertiseId = Ex.ExpertiseId




Hotel Table : 
HotelId   HotelName
1         Barcelona
2         Berlin


Media Table :
MediaID   MediaUrl      HotelId
1         www.xxx.com   1
2         www.xxx.com   1
3         www.xxx.com   1
4         www.xxx.com   1


Location Table :
LocationId   Adress          HotelId 
1            xyz, Berlin     1
2            xyz, Nice       1
3            xyz, Sevilla    1
4            xyz, Barcelona  1


Comment Table :
CommentId   Comment             HotelId
1           you are cool        1
2           you are great       1
3           you are bad         1
4           hmm you are okey    1

这仅是示例!我的数据库中有9999999家酒店。想象一下,一家酒店也许有100张图片,也许是零张。我不知道这一点。我的结果需要20间饭店(分页)。但是20家酒店意味着可能有1000行或100行。

1 个答案:

答案 0 :(得分:2)

首先,查询的可读性/表关系写得不好。我已经更新并缩进以尝试显示表/如何在层次相对论中相关。

您还想进行分页,让我们回到这一点。您是否打算将每条记录显示为一个可能的项目,还是打算显示“父”级别的数据集...例如,因此每个媒体,每个用户或任何对象只有一个实例,则一旦输入选择您将显示该实体的详细信息?如果是这样的话,我将在顶层进行DISTINCT查询,或者至少获取带有必须在下一层显示的子记录数(*)的几列。

此外,混合内部,左侧和右侧连接可能会造成混淆。通常,右联接意味着您需要联接右表中的记录。是否可以将其重写为将所有必需的表都保留在左侧,并且不需要将其左联接到辅助表中?

澄清所有这些关系肯定会与您试图摆脱分页的背景有所帮助。我会检查评论,但如果篇幅太长,我会用其他详细信息(而不是冗长的评论)来编辑您的原始帖子问题。

这是我的SOMEWHAT澄清查询,重写为我认为数据库中的关系。注意我的缩进显示表A-> B-> C-> D的可读性。所有这些都是(INNER)JOIN,表示它们在所有各自的表之间都必须具有匹配项。如果某些东西不总是存在的,它们将被更改为LEFT JOINs

SELECT  
      *
   FROM
      KisiselCoach KC
         JOIN WorkPlace WP
            ON KC.KisiselCoachId = WP.WorkPlaceOwnerId
         JOIN Album A
            ON KC.KisiselCoachId = A.AlbumId
            JOIN Media M
               ON A.AlbumId = M.AlbumId
         LEFT JOIN Rating R
            ON KC.KisiselCoachId = R.OylananId 
         JOIN FrUser Fr
            ON KC.CoachId = Fr.UserId 
         JOIN UserJob UJ
            ON KC.KisiselCoachId = UJ.UserJobOwnerId 
            JOIN Job J
               ON UJ.JobId = J.JobId 
         JOIN UserExpertise UserEx
            ON KC.KisiselCoachId = UserEx.UserExpertiseOwnerId
            JOIN Expertise Ex
               ON UserEx.ExpertiseId = Ex.ExpertiseId

查询的可读性对您自己和/或任何协助或关注您的人都是大帮助。如果在相应的联接附近没有“ on”子句,那么遵循起来会非常混乱。

此外,这是您的PRIMARY表,其余为查找参考表。

每条评论的添加量

好吧,所以我更新了一个查询,该查询似乎与示例数据以及您要发布的内容没有上下文。就是说,我将仅从酒店列表和每家酒店的事物计数(*)开始,以便您可以详细说明您拥有多少东西。像

select
      H.HotelID,
      H.HotelName,
      coalesce( MedSum.recs, 0 ) as MediaItems,
      coalesce( LocSum.recs, 0 ) as NumberOfLocations,
      coalesce( ComSum.recs, 0 ) as NumberOfLocations
   from
      Hotel H
         LEFT JOIN
         ( select M.HotelID, 
                  count(*) recs
              from Media M
              group by M.HotelID ) MedSum
            on H.HotelID = MedSum.HotelID
         LEFT JOIN
         ( select L.HotelID, 
                  count(*) recs
              from Location L
              group by L.HotelID ) LocSum
            on H.HotelID = LocSum.HotelID
         LEFT JOIN
         ( select C.HotelID, 
                  count(*) recs
              from Comment C
              group by C.HotelID ) ComSum
            on H.HotelID = ComSum.HotelID
   order by
      H.HotelName
   --- apply any limit per pagination

现在,这将返回每个顶级酒店,并且每个酒店可能存在或不存在的单个计数的总计数将返回每个旅馆,因此每个子检查都是LEFT-JOIN。展示20家不同酒店的页面。现在,只要一个人选择了一家旅馆,您就可以深入了解该旅馆的位置,媒体和评论。

现在,尽管此方法可以工作,但每次查询都必须进行这些计数可能会非常耗时。您可能希望将计数器列添加到您的主要酒店表中,以表示此处要执行的计数。然后,通过每晚的某个过程,您可以一次更新计数,以便在所有历史记录中进行计数,然后仅更新自先前日期以来具有新活动的那些旅馆的计数。不像您一天要有1,000,000条新图像,新位置,新评论的帖子,而是22,000条,那是您要重新更新计数的唯一酒店记录。仅基于添加的最新条目,每个增量周期都会很短。对于网络而言,在可行的情况下节省一些预先汇总的计数,总和等可以节省大量时间。