MySQL - 将这两个查询与连接或子查询一起加入?

时间:2013-03-23 20:18:53

标签: mysql query-optimization greatest-n-per-group

此查询返回给定特定traceid值所需的数据(在此示例中为50,这是两个表中存在的密钥,tblResultstblTraces

SELECT count(changed)
FROM (
    SELECT changed
    FROM tblResults
    WHERE traceid = 50
    AND changed = 1
    ORDER BY resultid DESC
    LIMIT 0,20
) as R

我想对每个traceid几乎运行以上查询(因此,为每个traceid选择20行,而不仅仅是traceid 50,因此3个traceid将意味着60行)。下面这个简单的选择获得了所需的traceid值:

SELECT `traceid` FROM `tblTraces` WHERE `enabled` = 1

如何将两个查询“粘合”在一起?

所以我想象一个类似下面的查询,除了它不起作用,因为子查询返回多行(我想要的):

SELECT count(changed)
FROM (
    SELECT changed
    FROM tblResults
    WHERE traceid = (
                     SELECT `traceid` FROM `tblTraces` WHERE `enabled` = 1
                    )
    AND changed = 1
    ORDER BY resultid DESC
    LIMIT 0,20
) as R

5 个答案:

答案 0 :(得分:1)

这是另一种方法。我改编了Bill Karwin's example。有关更全面的解释,请参阅他的帖子。

SELECT x.traceId, COUNT(*)
FROM (
  SELECT a.*
    FROM tblResults a
    -- Be sure not to exclude tblResults which are the only record in the trace
    LEFT OUTER JOIN tblResults b
      -- We're going to count how many rows came "before" this one
      ON a.changed = b.changed
     AND a.traceId = b.traceId
     AND a.resultId < b.resultId
   WHERE a.changed = 1
     AND a.traceId IN (SELECT traceId FROM tblTraces WHERE enabled = 1)
   GROUP BY a.resultId
  HAVING COUNT(*) < 20      -- Eliminate rows ranked higher than 20
   ORDER BY b.resultId DESC -- when we rank them by resultid
) x GROUP BY x.traceId

外部查询仅用于验证每个traceid包含不超过20个选定记录,内部查询是您实际感兴趣的结果集。

答案 1 :(得分:1)

虽然我对这个答案不满意,但对于较小的表格来说这可能是最简单的:

SELECT tblTraces.traceid, LEAST(20, SUM(tblResults.changed))
FROM tblTraces
    LEFT JOIN tblResults
    ON tblTraces.traceid = tblResults.traceid
WHERE tblTraces.enabled = 1
AND tblResults.traceid.changed = 1
GROUP BY tblTraces.traceid

列的限制确实使加入变得复杂。

答案 2 :(得分:1)

目前尚不清楚您是否需要计算这些(每个迹线限制为20个)结果或实际结果。仅限计数,有一种简单的方法:

  SELECT t.traceid,
         LEAST(COUNT(*),20) AS cnt
  FROM tblTraces AS t
    JOIN tblResults AS r
      ON r.traceid = t.traceid
  WHERE t.enabled = 1
    AND r.changed = 1
  GROUP BY t.traceid ;

SQL-Fiddle

中进行测试

答案 3 :(得分:0)

你可以像这样做一个内连接吗

select count(traceid)
  from tblResults a inner join tblTraces b on a.traceid = b.traceid
   and b.enabled = 1
   and a.changed = 1

或者我在这里错过了其他什么?

答案 4 :(得分:0)

在MySQL中,没有简单的方法可以做到这一点。在其他数据库中,您只需使用row_number(),但它不可用。

这是一种方法,假设resultId在每一行都是唯一的:

select t.traceId, count(changed)
from (select traceid, ResultId, changed,
             (select count(*) from tblResults r2 where r2.traceId = r.traceId and r2.ResultId >= r.ResultId and r2.changed = 1) as seqnum
      from tblResults r join
           tblTraces t
           on r.TraceId = t.TraceId and t.enabled = 1
      where r.changed = 1
    ) t
where seqnum <= 20
group by traceId

如果您不想按traceid进行此操作,只想要总计数,请删除group by并将select更改为count(changed)