聚集“仅一次”联接中的1行还是2行

时间:2019-11-05 09:54:22

标签: mysql sql mariadb

我正在尝试运行一个聚合查询,其中联接可以在联接表中找到0、1或2行。 我想聚合“仅一次”,无论联接是找到1还是2个匹配行。

最小的例子。

+--------------+--------+-----------+
| container_id | thing  | alternate |
+--------------+--------+-----------+
|            1 | box    |         0 |
|            1 | box    |         1 |
|            1 | hat    |         0 |
|            2 | monkey |         0 |
|            3 | monkey |         1 |
|            3 | chair  |         1 |
+--------------+--------+-----------+

+--------------+------+
| container_id | uses |
+--------------+------+
|            1 |    3 |
|            2 |    1 |
|            3 |    2 |
+--------------+------+

您可以看到“框”两次与1号容器ID关联。一次使用alternate = 0,一次使用alternate = 1。

SELECT 
    thing, COUNT(DISTINCT ct.container_id) AS occurrencs, SUM(uses) AS uses 
FROM 
    container_thing AS ct 
INNER JOIN 
    container_usage AS cu ON cu.container_id = ct.container_id 
GROUP BY 
    thing

给予:

+--------+------------+------+
| thing  | occurrencs | uses |
+--------+------------+------+
| box    |          1 |    6 |
| chair  |          1 |    2 |
| hat    |          1 |    3 |
| monkey |          2 |    3 |
+--------+------------+------+

但我真正想要的是:

+--------+------------+------+
| thing  | occurrencs | uses |
+--------+------------+------+
| box    |          1 |    3 |
| chair  |          1 |    2 |
| hat    |          1 |    3 |
| monkey |          2 |    3 |
+--------+------------+------+

我希望3作为第一行的使用值,因为“盒子”在总共使用了3次的容器中。由于使用“ alternate”列,因此该值得到6。 我可以以不同的方式加入或以不同的方式分组,还是可以在SUM表达式中对每个不同的事物仅进行一次SUM运算,而不论alter的值如何?

(请注意,事物可以在容器中交替显示,也可以不同时显示或不同时显示。)

设置最小示例所需的SQL:

-- Set up db
CREATE DATABASE sumtest;
USE sumtest;

-- Set up tables
CREATE TABLE container (id INT PRIMARY KEY);
CREATE TABLE container_thing (container_id INT, thing NVARCHAR(10), alternate BOOLEAN);
CREATE TABLE container_usage (container_id INT, uses INT);

-- Insert data
INSERT INTO container (id) VALUES (1), (2), (3);
INSERT INTO container_thing (container_id, thing, alternate) VALUES (1, 'box', FALSE), (1, 'box', TRUE), (1, 'hat', FALSE), (2, 'monkey', FALSE), (3, 'monkey', TRUE), (3, 'chair', TRUE);
INSERT INTO container_usage VALUES (1, 3), (2, 1), (3, 2);

-- Query
SELECT thing, COUNT(DISTINCT ct.container_id) AS occurrencs, SUM(uses) AS uses FROM container_thing AS ct INNER JOIN container_usage AS cu ON cu.container_id = ct.container_id GROUP BY thing;

2 个答案:

答案 0 :(得分:0)

如果只想使用..,则不应在join ..中执行总和,因为该联接会为每个macthing ON子句产生T1xT2行
其中N是来自table1的行数,而M是来自table2的行数,因此在box的情况下,您有2 x 1的值3 = 6。

为避免这种情况,您应该将container_usage与subqiery一起加入以得到关于container_thing计数的综合结果

select t.thing, t.count_container,  cu.uses 
from (
  SELECT thing,  container_id, COUNT(DISTINCT ct.container_id)  count_container
  FROM  container_thing 
  GROUP BY thing, container_id
) t 
inner join  container_usage AS cu ON cu.container_id = t.container_id  

答案 1 :(得分:0)

您可以通过仅从派生表中的DISTINCT中选择container_idthing的{​​{1}}值并将它们container_thing { 1}}:

JOIN

输出

container_usage

Demo on dbfiddle