0

编辑:我使用的是 10.4.11-MariaDB 版本。这是一些创建图示表格的代码

CREATE TABLE cats (
  c_id        INT            PRIMARY KEY   AUTO_INCREMENT,
  c_name      VARCHAR(255)   NOT NULL      UNIQUE
);

CREATE TABLE stock (
  p_id         INT            PRIMARY KEY   AUTO_INCREMENT,
  c_id        INT            NOT NULL,
  level         DECIMAL(10,2)  NOT NULL,
  rating   DECIMAL(10,2)  NOT NULL      DEFAULT 0.00
);

CREATE TABLE orders (
  p_id         INT            NOT NULL,
  sales           INT            NOT NULL
);

INSERT INTO cats (c_id, c_name) VALUES
(1, 'Boat'),
(2, 'Plane'),
(3, 'Car'), 
(4, 'Bike');

INSERT INTO stock (p_id, c_id, level, rating) VALUES
(1, 1, 145.65, 41),
(2, 1, 915.06, 49),
(3, 1, 981.36, 64),
(4, 1, 727.81, 29),
(5, 2, 678.19, 51),
(6, 2, 808.13, 43),
(7, 2, 711.10, 17),
(8, 3, 503.34, 92),
(9, 4, 292.41, 19),
(10, 4, 15.67, 36);


INSERT INTO orders (p_id, sales) VALUES
(1, 2),
(2, 4),
(9, 4),
(3, 2),
(8, 4),
(6, 3),
(2, 1),
(10, 2),
(8, 3),
(1, 4);

我将尝试彻底解决这个问题,因为我之前已经解决了这个问题,所以如果我需要提供任何其他信息,请告诉我。我将从三个代表我正在使用的数据的示例表开始,命名为catsstockorders(如果重要,全部小写)。

在此处输入图像描述

基本思想是每个p_id都有一个关联ratinglevel, 和sales值,并且p_id值可以通过它们共享的 进行分类c_id。每个p_idinstock都是独一无二的,只属于一个c_id。我的目标是生成一个表,该表对 、 和 列的聚合执行一些简单的rating计算levelsalesc_name. 我已经按照它们所属的颜色p_id对它们进行了颜色编码,希望能让事情更容易解释。c_id下面是我要制作的表格示例:

在此处输入图像描述

编辑:汽车的最低评分应该是 92,而不是 8

如您所见,我想选择四列:

  • 中的每个值c_name
  • 共享对应的p_id值的数量c_idc_name
  • 每个类别中包含rating的最小值p_id
  • 每个类别level中所有值的平均值p_id
  • 每个类别sales中所有值的总和p_id

我还想在底部有一行,对整个p_id值群体进行这些相同的计算,忽略类别。即,具有 的总和# of P_id's、 的最小值min rating、 的平均值avg level和 的总和的行# of sales。注意orders不包括every p_idin stock,有些p_id值是重复的;重要的是中间三行p_id只包含一次,无论它们出现多少次orders。同样,最后一列必须对现有p_id值的销售额求和,并按类别对它们进行分组。

我写了这个查询来尝试产生这个:

SELECT c_name, COUNT(p_id), MIN(rating), FORMAT(AVG(level),2), (SELECT SUM(sales) FROM orders JOIN stock USING(p_id))

FROM stock

JOIN cats USING(c_id)

GROUP BY c_name ASC WITH ROLLUP

这几乎完全符合我的要求,除了最后一列的问题,它只显示所有p_id价值组合的总销售额,而不管类别如何。我想在 SELECT 语句中使用子查询来计算该列,就好像我在 JOINing with 之后orders用LEFT JOIN 代替,列将仅根据在. 我的想法是通过简单地选择我在子查询中需要的最后一列所需的值来避免这种情况,但是我正在努力弄清楚当映射 from to仅存在于.stockstockcatsp_idordersproduct_idcategory_idstock

从本质上讲,我认为我的问题归结为不知道如何让我的中间三列基于列聚合数据p_idstock同时确保最后一列只取自orders. 谁能给我建议?

如果我需要更具体,请告诉我。

4

2 回答 2

1

对于您的示例数据,这将起作用:

SELECT c.c_name, t.`# of p_ids`, t.`min rating`, t.`avg level`,
       COALESCE(
         SUM(o.sales),
         (SELECT SUM(sales) FROM orders)  
       )  `# of sales`
FROM (
  SELECT c_id, 
    COUNT(p_id) `# of p_ids`, 
    MIN(rating) `min rating`, 
    FORMAT(AVG(level), 2) `avg level`
  FROM stock
  GROUP BY c_id WITH ROLLUP
) t 
LEFT JOIN cats c ON c.c_id = t.c_id
LEFT JOIN stock s ON s.c_id = t.c_id
LEFT JOIN orders o ON o.p_id = s.p_id
GROUP BY t.c_id, c.c_name, t.`# of p_ids`, t.`min rating`, t.`avg level` 
ORDER BY c.c_name IS NULL, c.c_id

请参阅演示
结果:

| c_name | # of p_ids | min rating | avg level | # of sales |
| ------ | ---------- | ---------- | --------- | ---------- |
| Boat   | 4          | 29         | 692.47    | 13         |
| Plane  | 3          | 17         | 732.47    | 3          |
| Car    | 1          | 92         | 503.34    | 7          |
| Bike   | 2          | 19         | 154.04    | 6          |
|        | 10         | 17         | 577.87    | 29         |
于 2020-05-11T20:47:01.400 回答
1

您可以通过使用几个聚合作为表表达式来获得您想要的结果;然后您只需将它们连接在一起即可产生完整的结果。

例如:

select
  x.c_name,
  x.number_of_pids,
  x.min_rating,
  x.avg_level,
  s.sum_sales
from (
  select
    c.c_id,
    max(c.c_name) as c_name,
    count(distinct s.p_id) as number_of_pids,
    min(s.rating) as min_rating,
    avg(s.level) as avg_level
  from cats c
  left join stock s on s.c_id = c.c_id
  group by c.c_id
) x
left join (
  select
    s.c_id, sum(sales) as sum_sales
  from stock s
  left join orders o on o.p_id = s.p_id
  group by s.c_id
) s on s.c_id = x.c_id
于 2020-05-11T20:53:27.397 回答