我如何离开加入子查询

时间:2015-11-18 19:50:42

标签: mysql sql mariadb

我有这样的数据,我正在尝试获得一个用户列表,其中包含已完成的唯一活动的总数以及所做的唯一活动的所有点的总和,因此,例如,如果用户重复活动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;

在完成表中添加了一个新行,以帮助说明我需要的内容。

2 个答案:

答案 0 :(得分:0)

您的查询可以简化为

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

答案 1 :(得分:0)

我认为我设法达到我想要的水平,但这是一个低效的陈述?

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