Mysql “聚合”;“仅一次”;连接中是否有1行或2行

Mysql “聚合”;“仅一次”;连接中是否有1行或2行,mysql,sql,mariadb,Mysql,Sql,Mariadb,我正在尝试运行聚合查询,其中联接可以在联接表中找到0、1或2行。 我希望聚合“仅一次”,而不管联接是找到1行还是2行匹配的行 最低限度的例子 +--------------+--------+-----------+ | container_id | thing | alternate | +--------------+--------+-----------+ | 1 | box | 0 | | 1 | box |

我正在尝试运行聚合查询,其中联接可以在联接表中找到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 |
+--------------+------+
您可以看到“box”与容器标识号1关联了两次。一次使用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作为第一行中使用的值,因为“box”位于总共使用了三次的容器中。由于“alternate”列,该值为6我是否可以以不同的方式加入或分组,或者在求和表达式中表示为每个不同的事物只求和一次,而不考虑alternate的值?

(请注意,对象可以显示在包含alternate、Not alternate或两者的容器中。)

设置最小示例所需的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;

如果你只想使用。。那么您不应该在join中执行求和。。因为join为每个macthing ON子句生成T1xT2行
其中N是表1中的行数,M是表2中的行数,因此在框中为2 x 1,值为3=6

为了避免这种情况,您应该将container_用法与container_thing计数的aggreated result子项连接起来

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  

您可以通过在派生表中从
container\u thing
中选择
container\u id
thing
DISTINCT
值,然后将其连接到
container\u usage

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

thing   occurrences     uses
box     1               3
chair   1               2
hat     1               3
monkey  2               3

更新您的问题,并将预期结果添加为表格文本。非常感谢。在子查询中使用GROUP BY或在@Nick的答案中使用DISTINCT之间是否有任何区别(性能方面)?因为性能实际上是相同的。。但是计数(DISTINCT ct.container_id)和分组方式的结果对于DISTINCT.是不同的。。(在本例中,返回相同的值,但永远不会返回)。。。你把我的答案编辑错了哦,对不起。对于最小的例子,在我的实际问题中,count_container列似乎没有做任何事情,所以我删除了它。我真的只是想修正“selet”中的拼写错误,但至少需要6个字符才能修改,所以我也这么做了:)是DISTINCT还是GROUP BY更正确?结果何时不同?如果使用聚合函数,则不能使用DISTINCT,但必须使用group by。。若您不使用aggreation函数并希望避免重复的行,那个么您需要distinct子句。。distinct子句只减少重复的行。。不允许聚合功能。。如果您的查询涉及聚合功能,则需要group by…非常感谢。在子查询中使用DISTINCT或在@scaisEdge的答案中使用GROUP BY之间是否有任何区别(性能方面?)?在性能方面可能不会有太多区别;这取决于你的数据,哪一个是最有效的。