当前位置: 首页 > 知识库问答 >
问题:

mysql分页左联接与联合限制

朱兴学
2023-03-14

我有一个表'gems'在那里存储帖子(例如blog)。对帖子的回复也存储在同一个表中,其中有一个字段存储父帖子的密钥。每个帖子都可以附上文件。

我需要得到一个与相关的回复和附加文件的帖子列表。因此“gems”有多个左联接--一个连接到它自己,一个连接到带有文件名的“gemdetail”。此查询有效:

SELECT g.gemid as gemidx, g.title, gemdetail.filename, r.gemid as rgemid, r.title, r.filename
FROM (SELECT * FROM gems WHERE gems.grade = '7' LIMIT 0, 10) g 
LEFT JOIN (SELECT x.title, x.gemid, x.replygemid, y.filename from gems x 
    LEFT JOIN gemdetail y ON x.gemid = y.gemid ) r ON g.gemid = r.replygemid 
LEFT JOIN gemdetail ON g.gemid = gemdetail.gemid 

但是,如果我每个帖子有20个回复和10个文件,那么返回的记录数是每个帖子200条。限制条款起作用,但这仍然是一大堆记录。另外,处理记录集也很麻烦。

我重写了查询,以使用一个联合,它将只返回40个记录,每个post(而不是200个)。联合有4个部分-1)返回前10个记录(限制)2)获取帖子的文件名3)获取回复4)获取回复的文件名

下面的UNION查询可以工作,只是我不能限制UNION的第一部分以外的任何其他部分的返回记录的数量。我可以将LIMIT语句放入联合的每个部分,但这是不正确的(我想将文件和回复限制在有限的10个帖子的集合中)。当我尝试在其中使用WHERE gemid时(从gems中选择gemid....)子句中的任何一个联合,我都会得到mySQL子查询限制错误。

SELECT g.gemid as gemidx, g.title, NULL as filename, NULL as rgemid, 'ag' as flag 
FROM (SELECT * FROM gems WHERE ISNULL(gems.replygemid) AND gems.grade = '7' LIMIT 0, 10) g
LEFT JOIN (SELECT * FROM gems) r ON g.gemid = r.replygemid  

UNION SELECT g.gemid as gemidx, g.title, gemdetail.filename as filename, NULL as rgemid, 'bf' as flag 
FROM (SELECT * FROM gems WHERE ISNULL(gems.replygemid) AND gems.grade = '7') g 
INNER JOIN gemdetail ON g.gemid = gemdetail.gemid

UNION SELECT g.replygemid as gemidx, g.title, NULL as filename, g.gemid as rgemid, 'cr' as flag 
FROM (SELECT * FROM gems WHERE NOT ISNULL(gems.replygemid) AND gems.grade = '7') g 

UNION SELECT g.replygemid as gemidx, g.title, gemdetail.filename as filename, g.gemid as rgemid, 'df' as flag 
FROM (SELECT * FROM gems WHERE NOT ISNULL(gems.replygemid) AND gems.grade = '7') g 
INNER JOIN gemdetail ON g.gemid = gemdetail.gemid 

ORDER BY gemidx desc, rgemid, flag

请帮帮忙。有没有一种方法可以有效地选择(为了分页的缘故)只有10个帖子和它的所有相关的回复和文件?谢谢你花时间读这篇文章。我已经花了两天的时间在这上面,我的极限(糟糕的双关语本意...)。

共有1个答案

林涵映
2023-03-14

这是一个游戏,但这段代码有点讨厌,所以您可能不想使用它。但现在这是在忽略文件。注意,我在我的一个表上得到了一些类似的东西,然后从它导出了这个,但是我没有直接测试这个,所以里面可能有错别字。

SELECT gems.gemid as gemidx, gems.title, r.gemid as rgemid, r.title, r.filename
FROM gems
INNER JOIN (SELECT gems.*, @runningtotal:=@runningtotal+1 AS CurrentTotal
FROM (SELECT @runningtotal := 0)Deriv1, gems 
ORDER BY replygemid) r
INNER JOIN (SELECT replygemid, MIN(CurrentTotal) AS MinTotal
FROM (SELECT replygemid, @runningtotal:=@runningtotal+1 AS CurrentTotal
FROM (SELECT @runningtotal := 0)Deriv1, gems 
ORDER BY replygemid) Deriv2
GROUP BY replygemid) Deriv5
ON Deriv4.replygemid = Deriv5.replygemid 
AND Deriv4.CurrentTotal < Deriv5.MinTotal + 10
WHERE gems.grade = '7'

它所做的是使用一个subselect向回复添加一个序列号(由父级排序)。它使用这个子选择两次,一次是为了获取组的最小序列号,然后再一次用序列号带回所有的rowdetails。然后将其连接到序列号是该GEM的前10个中的一个的那些。

虽然我更喜欢将事情保留在一个SQL中,但我认为这已经到了这样一个阶段:它太慢了,不值得。

也许可以使用GROUP_CONCAT将文件详细信息添加到gem回复中,然后在代码中处理掉您不感兴趣的(例如,超过10个)

对不起,我想不出更有用的东西

 类似资料:
  • 问题内容: 我有一个表,我们称它为“ a”,它在涉及许多表的视图中用在左联接中。但是,我只想返回“ a”的行(如果它们也与另一个表“ b”联接)。所以现有的代码看起来像 但它返回的行太多,尤其是其中a在b中不匹配的行。我试过了 这给了我正确的结果,但是不幸的是,“ EXPLAIN PLAN”告诉我们,这样做会导致强制对a和b进行全表扫描,这使事情变得很慢。我的一位同事在b上建议了另一个LEFT J

  • 问题内容: 假设我们有下表t1和t2: 我们希望找到以下结果: 这基本上是右连接与左连接的并集。以下代码有效,但感觉很笨拙: 有没有更好的方法来实现这一目标? 问题答案:

  • 问题内容: 我的查询有问题。 MySQL查询: 我得到的错误是这样的: 选择时如何将其作为未知列? 我很困扰… 使用者: 兴趣: 已封锁: 问题答案: 如语法所示: 在MySQL 5.0.12中加入处理更改 以前,逗号运算符()和都具有相同的优先级,因此join表达式被解释为。现在具有更高的优先级,因此该表达式被解释为。此更改会影响使用子句的语句,因为该子句只能引用联接操作数中的列,并且优先级的更

  • 问题内容: 我已经搜索过,但没有找到明确的答案。以下哪一项对SQL Server的性能更好: 或者… 我尝试过同时运行这两个程序,但是很难确定。我会很高兴地解释一个为什么比另一个更快,或者这取决于情况。 问题答案: 您的两个查询不做相同的事情。特别是,如果两个表中的值重复,则第一个将返回重复的行。 如果要在其他两个表中的任何一个中查找行,我建议使用: 并且,在和中都创建索引。 您的原始查询哪个更快

  • 我有两个问题。两者都很好用: 第二个查询: 联合本: 工作正常,但我想添加左联接: DoSend工作...#1222-使用的SELECT语句具有不同的列数 你能帮我把这件事办好吗?

  • 问题内容: 以两个表为例:和。 列出产品详细信息,包括名称和ID,同时列出涉及产品的交易,包括日期,产品ID,客户等。 我需要显示一个网页,其中显示10个产品,每个产品的最近5个交易。到目前为止,如果mysql允许该部分,则似乎没有任何查询有效,并且下面的子查询也可以工作( 在“ where子句”中 出现 Unknown列“ ta.product_id”的 失败 :[ERROR:1054] )。