MySQL - 查找事务失败的订单百分比

时间:2016-04-30 19:37:39

标签: mysql sql select

我有一个包含3个相关列的order_transactions表。 id(事务尝试的唯一ID),order_id(正在尝试的命令的id),success int,如果失败则为0,以及1如果成功的话。

对于每个order_id,成功交易之前可能有0个或更多失败的交易。

问题是,我如何找到:

  • 从未成功交易的订单数量
  • 交易失败的订单数量(最终成功与否)
  • 从未发生过交易失败的订单数量(仅限成功)

我意识到这是一个不同的,分组的,也许是一个子选择等的组合,我只是不太熟悉这一点。感谢。

3 个答案:

答案 0 :(得分:1)

要获得从未有过成功交易的订单数量,您可以使用:

SELECT COUNT(*)
FROM (
  SELECT order_id
  FROM transactions 
  GROUP BY order_id
  HAVING COUNT(CASE WHEN success = 1 THEN 1 END) = 0) AS t

Demo here

使用查询可以获得交易失败(最终成功与否)的订单数量:

SELECT COUNT(*)
FROM (
  SELECT order_id
  FROM transactions
  GROUP BY order_id
  HAVING COUNT(CASE WHEN success = 0 THEN 1 END) > 0) AS t

Demo here

最后,要获得从未发生过失败的订单数量(仅限成功):

SELECT COUNT(*)
FROM (
   SELECT order_id
   FROM transactions
   GROUP BY order_id
   HAVING COUNT(CASE WHEN success = 0 THEN 1 END) = 0) AS t

Demo here

答案 1 :(得分:1)

你想要"计数"满足多行特定条件的订单,因此我以GROUP BY order_id

开头
SELECT ...
  FROM mytable t 
 GROUP BY t.order_id

要查明某个特定订单是否曾经有过失败的交易等,我们可以在表达式上使用聚合," test"条件。

例如:

SELECT MAX(t.success=1)         AS succeeded
     , MAX(t.success=0)         AS failed
     , IF(MAX(t.success=1),0,1) AS never_succeeded
  FROM mytable t 
 GROUP BY t.order_id

该查询的SELECT列表中的表达式是MySQL的简写。我们可以使用更长的表达式(MySQL IF()函数或ANSI CASE表达式)来获得相同的结果,例如

  CASE WHEN t.success = 1 THEN 1 ELSE 0 END 

我们可以在SELECT列表中包含`order_id`列以进行测试。我们可以将每个order_id的结果与原始表中的行进行比较,以验证返回的结果是否符合规范。

获得"计数"对于订单,我们可以将查询作为内联视图引用,并在SELECT列表中使用聚合表达式。

例如:

SELECT SUM(r.succeeded)              AS cnt_succeeded
     , SUM(r.failed)                 AS cnt_failed
     , SUM(r.never_succeeded)        AS cnt_never_succeeded 
  FROM ( 
         SELECT MAX(t.success=1)         AS succeeded
              , MAX(t.success=0)         AS failed
              , IF(MAX(t.success=1),0,1) AS never_succeeded
           FROM mytable t 
          GROUP BY t.order_id
       ) r

由于SELECT列表中的表达式返回0,1或NULL,我们可以使用SUM()聚合来获取计数。要使用COUNT()聚合,我们需要返回NULL来代替0(FALSE)值。

SELECT COUNT(IF(r.succeeded,1,NULL))       AS cnt_succeeded
     , COUNT(IF(r.failed,1,NULL))          AS cnt_failed
     , COUNT(IF(r.never_succeeded,1,NULL)) AS cnt_never_succeeded 
  FROM ( 
         SELECT MAX(t.success=1)         AS succeeded
              , MAX(t.success=0)         AS failed
              , IF(MAX(t.success=1),0,1) AS never_succeeded
           FROM mytable t 
          GROUP BY t.order_id
       ) r

如果要计算所有order_id的计数,请在外部查询中添加COUNT(1)表达式。如果您需要百分比,请进行除法并乘以100,

例如

SELECT SUM(r.succeeded)                    AS cnt_succeeded
     , SUM(r.failed)                       AS cnt_failed
     , SUM(r.never_succeeded)              AS cnt_never_succeeded 
     , SUM(1)                              AS cnt_all_orders
     , SUM(r.failed)/SUM(1)*100.0          AS pct_with_a_failure
     , SUM(r.succeeded)/SUM(1)*100.0       AS pct_succeeded
     , SUM(r.never_succeeded)/SUM(1)*100.0 AS pct_never_succeeded
  FROM ( 
         SELECT MAX(t.success=1)         AS succeeded
              , MAX(t.success=0)         AS failed
              , IF(MAX(t.success=1),0,1) AS never_succeeded
           FROM mytable t 
          GROUP BY t.order_id
       ) r

(此处的百分比是与不同order_id值的计数进行比较,而不是表中的总行数。)

答案 2 :(得分:0)

成功订单

select count(*) from 
( select distinct order_id  from my_table where success = 1 ) as t;

订单不成功

select count(*) from 
( select distinct order_id  from my_table where success = 0 ) as t;

从未提交过交易

select count(*) from 
( select distintc order_id  from my_table where id not in 
       (select distinct order_id  from my_table where success = 0) ) as t;