【问题标题】:Mysql calculating percentage of repeat rowsMysql计算重复行的百分比
【发布时间】:2012-09-05 12:53:18
【问题描述】:

所以我试图计算我系统中每家餐厅的重复订单数量。这被定义为从该餐厅多次订购的用户数量(基于他们的电子邮件地址,eo_email)。架构下的示例

这是代表我的餐厅的表格

CREATE TABLE IF NOT EXISTS `lf_restaurants` (
  `r_id` int(8) NOT NULL AUTO_INCREMENT,
  `r_name` varchar(128) DEFAULT NOT NULL,
  PRIMARY KEY (`r_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 ;

INSERT INTO `lf_restaurants` (`eo_id`, `eo_ref_id`) VALUES
('1', 'Restaurant X'),
('2', 'Cafe Y');

这是我的订单表

CREATE TABLE IF NOT EXISTS `ecom_orders` (
  `eo_id` mediumint(9) NOT NULL AUTO_INCREMENT,
  `eo_ref_id` varchar(12) DEFAULT NOT NULL,
  `eo_email` varchar(255) DEFAULT NOT NULL,
  `eo_order_parent` int(11) NOT NULL,
  PRIMARY KEY (`eo_id`),
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 ;

INSERT INTO `ecom_orders` (`eo_id`, `eo_ref_id`, `eo_email`, `eo_order_parent`) VALUES
('', '', 'a@a.com', '1'),
('', '', 'a@a.com', '1'),
('', '', 'a@a.com', '1'),
('', '', 'a@a.com', '1'),
('', '', 'a@a.com', '1'),
('', '', 'b@b.com', '1'),
('', '', 'b@b.com', '1'),
('', '', 'c@c.com', '1'),
('', '', 'd@d.com', '1'),
('', '', 'e@e.com', '1'),
('', '', 'a@a.com', '2'),
('', '', 'c@c.com', '2'),
('', '', 'c@c.com', '2'),
('', '', 'e@e.com', '2');

所以餐厅 X (r_id 1) 有 10 个订单。用户 a@a.com 和 b@b.com 曾多次从该餐厅点过餐,而 c@c.com、d@d.com 和 e@e.com 仅点过一次,因此需要退货40%

Cafe Y (r_id 2) 有 4 个订单。用户c@c.com 下单两次,用户a@a.com 和e@e.com 只下单一次,所以需要退货33%

我不确定发布我已经获得的内容会很好,因为我一直遇到“子查询有超过 1 个结果”,或者如果我将该子查询包装在它自己的虚拟查询中并带有计数,它不会让我使用主查询中我需要的字段,例如 r_id。但这里是:

SELECT r_name,
    (SELECT COUNT(*) AS cnt_users
        FROM (
            SELECT *
            FROM ecom_orders
            WHERE eo_order_parent = r_id
            GROUP BY eo_email
        ) AS cnt_dummy
    ) AS num_orders,
    (SELECT COUNT(*) AS cnt
        FROM ecom_orders
        WHERE eo_order_parent = r_id
        GROUP BY eo_order_parent, eo_email

    ) AS num_rep_orders
    FROM lf_restaurants
    ORDER BY num_orders DESC

num_orders 子查询说它不能识别 r_id,因为我猜这是由于执行的顺序造成的

num_rep_orders 子查询以多行的形式返回,但我真的希望它只返回一个值,如果我将其设置为 num_orders 子查询但随后会遇到 r_id 不存在问题,我可以这样做。

所以我的问题是:我如何获得这些我需要的值而不遇到子查询有超过 1 行,并且 r_id 不存在?

然后从这 2 个值中我可以计算出百分比,所有这些都应该是肉汁 :) 非常感谢任何帮助!

【问题讨论】:

    标签: mysql count subquery percentage


    【解决方案1】:

    所以餐厅 X (r_id 1) 有 10 个订单。用户 a@a.com 和 b@b.com 有 多次从该餐厅订购,以及 c@c.com、d@d.com 和 e@e.com 只订购过一次,所以需要退货 40%

    Cafe Y (r_id 2) 有 4 个订单。用户 c@c.com 已订购两次,用户 a@a.com 和 e@e.com 只订购过一次,所以需要退货 33%

    好的。因此,让我们从获取回头客的数量开始。

    SELECT eo_order_parent, eo_email, COUNT(eo_email) AS orders FROM ecom_orders
        GROUP BY eo_order_parent, eo_email
        HAVING orders > 1;
    

    以及不同客户的总数

    SELECT eo_order_parent, COUNT(eo_email) FROM ecom_orders
        GROUP BY eo_order_parent;
    

    但我们可以一次性完成:

    SELECT eo_order_parent,
        SUM(CASE WHEN orders > 1 THEN 1 ELSE 0 END) AS repeats,
        SUM(1) AS total FROM
        (
            SELECT eo_order_parent, eo_email, COUNT(*) AS orders FROM ecom_orders
                GROUP BY eo_order_parent, eo_email
        ) AS eo_group_1
    GROUP BY eo_order_parent;
    

    这给出了:

    +-----------------+---------+-------+
    | eo_order_parent | repeats | total |
    +-----------------+---------+-------+
    |               1 |       2 |     5 |
    |               2 |       1 |     3 |
    +-----------------+---------+-------+
    2 rows in set (0.00 sec)
    

    那么 2/5 是你的 40%,1/3 是 33%。

    【讨论】:

    • 老兄...!很好的回答,非常优雅的解决方案:) 非常感谢!
    【解决方案2】:

    以下查询计算回头客数和每家餐厅的总客户数

    SELECT
      u.r_id,
      u.r_name,
      SUM(u.no_orders > 1) AS repeats,
      SUM(u.no_orders) AS orders,
      COUNT(u.eo_email) AS customers
    FROM (
        SELECT
          r.*,
          o.eo_email,
          COUNT(o.eo_id) AS no_orders
        FROM lf_restaurants r
        LEFT JOIN ecom_orders o ON o.eo_order_parent = r.r_id
        GROUP BY o.eo_email
    ) u
    GROUP BY
      r.r_id;
    

    子查询首先计算每个客户/餐厅对的订单数。外部查询由此计算顾客数量、回头客数量和每家餐厅的顾客总数。您还可以计算百分比(但这不必在查询中完成)。

    【讨论】:

    • 感谢您的回答,但“字段列表”中的“u.no_order”列未知
    猜你喜欢
    • 2013-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-05
    • 1970-01-01
    • 2022-01-23
    • 2012-04-05
    • 1970-01-01
    相关资源
    最近更新 更多