【问题标题】:How to count percentage based on several condition mysql from different table如何根据来自不同表的几个条件mysql计算百分比
【发布时间】:2020-03-04 08:11:53
【问题描述】:

我有两个这样的表,sales.id_Location = location.id_location(这不是真实数据,只是数据虚拟)在销售表上,id_order 是交易历史,createdAt 是交易发生的日期,sale 是金额交易量(kg),id_Location是与位置表中id_location相连的发货位置,createdby是买家。

CREATE TABLE sales
(
    id_order VARCHAR(50) NOT NULL,
    createdAt datetime NOT NULL,
    sale DECIMAL(14,2) NOT NULL,
    id_location varchar(50) NOT NULL,
    createdby varchar(50) NOT NULL,
    PRIMARY KEY(id_order,createdAt)
);

INSERT INTO sales (id_order, createdAt, sale, id_location, createdby)
VALUES(1,'2016-02-02',100, 1, 123),
      (2,'2017-03-02',150, 2, 233),
      (3,'2018-02-02',200, 3, 234),
      (4,'2016-03-03',150, 1, 123),
      (5,'2017-03-04',100, 2, 2334),
      (6,'2018-03-05',200,3, 234),
       (7,'2016-03-10',200, 1, 233),
      (8,'2017-02-01',150, 2, 124),
      (9,'2018-02-04',250, 3, 233),
      (10,'2018-02-05',300, 2, 124);

CREATE TABLE location
(
     id_location varchar(50) NOT NULL,
     location_city varchar(50) NOT NULL
);

INSERT INTO location(id_location, location_city)
VALUES (1, 'Jakarta'),
 (2, 'Depok'),
 (3, 'Bekasi');

select * from sales;
select * from location;

这是小提琴 https://dbfiddle.uk/?rdbms=mysql_5.7&fiddle=eac3dc2845bfa425fbd576cc18c72609

在这种情况下,我使用了 mysql 5.7 版,我想在这个条件下找出每个位置的销售统计数据

  1. 销售额在 '2016-02-01' 到 '2018-03-10' 之间

  2. 买家(createdby 列)在 '2018-03-10' 之前进行交易,并且至少在 '2016-02-01' - '2018- 之间进行交易再次 03-10',

因此,如果买家只是进行了一次交易,或者进行了多次交易,但在 '2016-02-01' 到 '2018-03-10' 之间根本没有交易,则不计入买家并且不包括在内

基于该条件和数据虚拟,预期结果如下:

+----------+----------+---------+----------------+--------------------+
| Location | sale(kg) | sale(%) | count id_order | count id_order (%) |
+----------+----------+---------+----------------+--------------------+
| Jakarta  |      450 |   26,48 |              3 |              33,33 |
| Depok    |      600 |   35,30 |              3 |              33,33 |
| Bekasi   |      650 |   38,22 |              3 |              33,33 |
| TOtal    |     1700 |     100 |              9 |                100 |
+----------+----------+---------+----------------+--------------------+

这是我的 SQL 语句:

SELECT 
  IFNULL(location.location_city, 'Total') AS `Location`, 
  SUM(sale) AS `sale(kg)`,
  SUM(sale) / (SELECT SUM(sale) FROM sales) * 100 AS `sale (%)`, 
  COUNT(id_order) AS `count(id_order)`,
  COUNT(id_order) / (SELECT COUNT(id_order) FROM sales) * 100 AS `count(id_order) (%)`
FROM sales, location
where sales.id_location = location.id_location
and createdAt <= '2018-03-04'
and EXISTS (select 1 from sales s2, location l2 where
sales.id_location = s2.id_location
and sales.id_location = l2.id_location and
createdAt >= '2016-02-01'
and createdAt <= '2018-03-04')
GROUP BY location WITH ROLLUP
having count(createdby) > 1;

这是小提琴 https://dbfiddle.uk/?rdbms=mysql_5.7&fiddle=eac3dc2845bfa425fbd576cc18c72609

【问题讨论】:

  • 请注意,我们停止以这种方式编写查询 ca。 1992.来吧。加入我们。
  • 注意!谢谢楼主
  • 不清楚...为什么要计算 createdby = 234 的销售额?他不符合条件 (2) - 他在 '2018-03-04' 或之前只有一次销售......
  • 对不起,先生,请检查我的编辑,非常感谢@Akina
  • 您的版本没有改变我所说的问题。期望的结果与条件不匹配。

标签: mysql select group-by sql-insert create-table


【解决方案1】:

测试

SELECT COALESCE(location_city, 'Total') AS `Location`, 
       SUM(sale) AS `sale(kg)`,
       SUM(sale) / ANY_VALUE(totalsum) * 100 AS `sale (%)`, 
       COUNT(id_order) AS `count(id_order)`,
       COUNT(id_order) / ANY_VALUE(totalcount) * 100 AS `count(id_order) (%)`
FROM sales
NATURAL JOIN location
NATURAL JOIN ( SELECT s1.createdby
               FROM sales s1
               GROUP BY s1.createdby
               HAVING SUM(s1.createdAt BETWEEN '2016-02-01' AND '2018-03-04')
                  AND SUM(s1.createdAt <= '2018-03-04') > 1 ) clients
JOIN ( SELECT SUM(sale) totalsum, 
              COUNT(id_order) totalcount 
       FROM sales ) totals
GROUP BY location_city WITH ROLLUP

fiddle(见小提琴中的 cmets)。


销售和计数 id_order 的总百分比应为 100,因为它是日期范围的总体统计数据,而不是数据虚拟数据的总体数据 - Fachry Dzaky

如果是这样,这些总值必须单独计算。测试

SELECT COALESCE(location_city, 'Total') AS `Location`, 
       SUM(sale) AS `sale(kg)`,
       SUM(sale) / ANY_VALUE(totalsum) * 100 AS `sale (%)`, 
       COUNT(id_order) AS `count(id_order)`,
       COUNT(id_order) / ANY_VALUE(totalcount) * 100 AS `count(id_order) (%)`
FROM sales
NATURAL JOIN location
NATURAL JOIN ( SELECT s1.createdby
               FROM sales s1
               GROUP BY s1.createdby
               HAVING SUM(s1.createdAt BETWEEN '2016-02-01' AND '2018-03-04')
                  AND SUM(s1.createdAt <= '2018-03-04') > 1 ) clients
JOIN ( SELECT SUM(sale) totalsum, 
              COUNT(id_order) totalcount 
       FROM sales
       NATURAL JOIN ( SELECT s1.createdby
                      FROM sales s1
                      GROUP BY s1.createdby
                      HAVING SUM(s1.createdAt BETWEEN '2016-02-01' AND '2018-03-04')
                         AND SUM(s1.createdAt <= '2018-03-04') > 1 ) clients ) totals
GROUP BY location_city WITH ROLLUP

fiddle

【讨论】:

  • 销售和计数 id_order 的总百分比应为 100,因为它是日期范围的总体统计数据,而不是数据虚拟数据的总体数据
  • 非常感谢先生,祝您有美好的一天,希望您一如既往的健康
  • 再来一次先生,根据您的查询,您没有放sales.id_location = location.id_location,是不是因为您放了自然连接?
  • @FachryDzaky 是的。 NATURAL JOIN 由具有相同名称的所有字段连接(赏金 - 只有一个字段的副本被放入输出,而不是两个)。如果这些字段具有不同的数据类型,则使用最前一个表的数据类型。
  • @FachryDzaky 在 FROM 中使用表的任何地方。 sales 表的 4 个副本 == 4 WHERE 条件。 fiddle.
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-15
  • 1970-01-01
  • 2014-04-03
相关资源
最近更新 更多