【问题标题】:SQL : How to calculate limited rows and reset the counterSQL:如何计算有限行并重置计数器
【发布时间】:2012-07-01 08:28:20
【问题描述】:

我正在处理一个问题,需要一些专家建议来解决这个问题,我的 sql 查询生成包含两列的输出,第一列显示 id(例如下表中的 abc-123),下一列显示对应的结果存储在db中的id是通过还是失败。

我需要实现,当分辨率通过时它应该显示成功尝试,在以下示例中,abc-123 第一次失败但 def-456 在下一次尝试中通过,因此成功率为 50%,现在计数器应该重置并转到下一行有通过,因此它应该显示 100%,再次当代码命中通过计数器重置然后进入下一个并显示 33%,因为最后有两个失败和一个通过,如何在 sql 中实现? (id 和 resolution 是列名)

**date**       **id resolution**    
 6/6/2012     abc-123   fail       50%
 6/7/2012     abc-456   pass    
 6/8/2012     abc-789   pass       100%
 6/9/2012     abc-799   fail       33%
 6/10/2012    abc-800   fail    
 6/1/2012     abc-900   pass

谢谢

【问题讨论】:

  • 写 'o/p' 而不是 'output' 只是令人困惑。
  • 是否有一些顺序或时间戳列来指示哪个项目在下一个之前?
  • 嗨 Holger,我修复了输出,id 在升序列中,也是的,还有一个按升序排列的日期列。
  • 嗨 Holger,我添加了一个按升序排列的日期列。
  • 1) 您在程序上考虑问题,而 SQL 使用集合。 2) 你对数据的分析对我来说毫无意义。为什么要将 6/6 和 6/7 的记录组合在一起计算百分比?他们不共享一个共同的ID。同一天不能有多个决议吗?那么,您将如何按百分比对它们进行分组?

标签: mysql sql


【解决方案1】:
SELECT
  *
FROM
  table
INNER JOIN
(
  SELECT
    MIN(g.id)   AS first_id,
    MAX(g.id)   AS last_id,
    COUNT(*)    AS group_size
  FROM
    table AS p
  INNER JOIN
    table AS g
      ON g.id > COALESCE(
                  (SELECT MAX(id) FROM table WHERE id < p.id AND resolution = 'pass'),
                  ''
                )
     AND g.id <= p.id
  WHERE
    p.resolution = 'pass'
  GROUP BY
    p.id
)
  AS groups
    ON  table.id >= groups.first_id
    AND table.id <= groups.last_id

【讨论】:

  • 我假设您的 id 列是 VARCHAR() 或类似的。这就是我在COALESCE() (包括所有id)中使用'' 的原因
  • @Dems : 按分辨率分组?
  • @yokoyoko - 不,GROUP BY p.id 在主子查询上。我已经将它添加到答案中:)
  • @yokoyoko - 因为在那个 sql fiddle 中,该表被称为 table1,但在某些地方您将其命名为 table,在其他地方将其命名为 table1。试试这个链接? sqlfiddle.com/#!2/177cb/8/0
  • @yokoyoko - 是的。组内成功率 = 100.0 / group_size。如果您只想在组中的第一条记录上显示它,那么您可以使用... CASE WHEN table.id = groups.first_id THEN 100.0 / groups.group_size ELSE NULL END AS pass_rate, 究竟如何使用数据取决于您,但查询应该为您提供计算所需的一切你想要你想要的地方。 sqlfiddle.com/#!2/6a3d5/3
【解决方案2】:

有不止一种方法可以做到这一点:

SELECT st.*, 
       @prev:=@counter + 1,
       @counter:= CASE 
         WHEN st.resolution = 'pass'
         THEN 0
         ELSE @counter + 1
       END c,
       CASE WHEN @counter = 0 
            THEN CONCAT(FORMAT(100/@prev, 2), '%') 
            ELSE '-' 
       END res
  FROM so_test st, (SELECT @counter:=0) sc

这里是proof of concept

【讨论】:

  • 实际上,分组查询的链接帮助很大。这个概念本身很简单:我们有两个变量,一个 (@prev) 累积失败,另一个 (@counter) 帮助第一个,但也充当某种独立触发器。 )
  • 是的,从我的角度来看,这些类型的任务最好通过一些程序方法来完成。 ) 但话又说回来,要求不同。
猜你喜欢
  • 1970-01-01
  • 2023-03-04
  • 1970-01-01
  • 1970-01-01
  • 2018-03-21
  • 1970-01-01
  • 2021-10-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多