【问题标题】:How do i left join a subquery我如何离开加入子查询
【发布时间】:2015-11-18 19:50:42
【问题描述】:

我有这样的数据,我正在尝试获取用户列表,其中包含完成的唯一活动总数和完成的所有独特活动点的总和,因此,例如,如果用户重复活动 1 3 次,将计为 100 以及其他活动等。

我试过了,但它似乎不起作用

SELECT *,
  ( SELECT COUNT(*) 
    FROM done 
     WHERE done.user_id = user.id 
  ) as activity_count
FROM
  user AS user
LEFT JOIN 
  (
    SELECT SUM(points), d.user_id
    FROM done AS d
    LEFT JOIN activity AS a
      ON d.activity_id = a.id
    GROUP BY user_id
  ) AS subtable 
ON  subtable.user_id = user.id

我的数据架构是这样的:

CREATE TABLE IF NOT EXISTS `user` (
  `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(45) NULL,
  PRIMARY KEY (`id`),
  UNIQUE INDEX `id_UNIQUE` (`id` ASC));
CREATE TABLE IF NOT EXISTS `activity` (
  `id` INT NOT NULL,
  `name` VARCHAR(45) NULL,
  `points` INT UNSIGNED NULL,
  PRIMARY KEY (`id`));
CREATE TABLE IF NOT EXISTS `done` (
  `id` INT NOT NULL,
  `user_id` INT UNSIGNED NULL,
  `activity_id` INT UNSIGNED NULL,
  `status` INT UNSIGNED NULL,
  PRIMARY KEY (`id`));

INSERT INTO user
  (`id`, `name`)
  VALUES
   (1, 'User 1'),
   (2, 'User 2'),
   (3, 'User 3'),
   (4, 'User 4');
INSERT INTO activity
   (`id`, `name`, `points`)
  VALUES
   (1, 'activity 1', 100), 
   (2, 'activity 2', 200),
   (3, 'activity 3', 300),
   (4, 'activity 4', 400);
INSERT INTO done
  (`id`, `user_id`, `activity_id`, `status`)
  VALUES
    (1, 1, 1, 2),
    (2, 2, 1, 3),
    (3, 1, 2, 2),
    (4, 3, 1, 1),
    (5, 2, 1, 3),
    (6, 4, 4, 2),
    (7, 3, 1, 1),
    (8, 1, 1, 3);

预期结果:

user_id,   count_of_unique_activities_done, sum_of_unique_activity_points
1,   2,  300;
2,   1,  100;
3,   1,  100;
4,   1,  400;

在完成表中添加了一个新行以帮助说明我需要什么。

【问题讨论】:

  • doesn't work 是什么意思?
  • 如果你想要唯一计数,应该使用 GROUP BY。
  • 想要的输出是什么?
  • @Ultimater 我正在寻找这样的用户列表,用户 ID,完成的独特活动总数,完成的独特活动的总点数将尝试编辑看看我是否可以添加我期望的示例输出的问题。

标签: mysql sql mariadb


【解决方案1】:

您的查询可以简化为

SELECT u.id, SUM(a.points), count(a.*)
FROM `user` u
LEFT JOIN done d ON done.user_id = u.id
LEFT JOIN activity a ON d.activity_id = a.id
GROUP BY u.id

【讨论】:

  • 只是一个问题,MySQL 接受 count(a.*) 吗?我以前从未见过这种建筑。这是什么意思?
  • @jarlh 您将计算非空 (a.*) 的数量。所以基本上,如果左连接命中一行,它就会被计算在内。如果您说 count(*) 或 count(1),它将返回行数,包括没有活动的行数。同样,如果您要求 count(a.points) 并且某个活动的积分为 NULL,则不会被计算在内。
  • 我明白了。谢谢你的解释!
  • @vkp 当我使用 (a.*) 我得到这个 sql 错误 *** 你的 SQL 语法有错误;检查与您的 MySQL 服务器版本相对应的手册,以了解在 ') 附近使用的正确语法。** 如果我使用 (*) 就可以了。结果也不是我想要的......它正在计算活动点的总和,无论活动是否相同......如果它们对于同一个用户是相同的,那么这些点应该只是 1 个实例,而不是多个实例。例如,用户 2 做了两次活动 1(100points),他的 points 列的结果应该是 100,而不是 200(这是 sql 语句返回的)
  • 更新了我的问题并添加了一个示例预期结果,以尝试显示我想要输出的内容。
【解决方案2】:

我想我设法得到了我想要的,但这是一个低效的陈述吗?

SELECT activity_done.id, SUM(activity_done.points) as total_points, user_c.name
FROM
    ( 
        SELECT done_c.user_id as id, points
        FROM 
            done as done_c
        LEFT JOIN
            activity as activity_c
        ON
            activity_c.id = done_c.activity_id
        GROUP BY
            done_c.`activity_id`,
            done_c.`user_id`
    ) as activity_done
LEFT JOIN
    user as user_c
    ON 
        user_c.id = activity_done.id
GROUP BY
    activity_done.id

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-04-27
    • 2012-04-11
    • 1970-01-01
    • 2019-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-27
    相关资源
    最近更新 更多