返回groupby的记录,计数为1

时间:2017-06-16 22:49:13

标签: sql

我有两张表user_expensesusers

user_expenses的外键是user_expenses.user_id,对应users.id

我想从两个表中获取一些信息,其中用户只有一笔费用。

我试了一下:

SELECT 
    users.id, users.email, users.stripe_plan, users.previous_plan, 
    users.created_at, user_expenses.created_at, user_expenses.description
FROM 
    users
INNER JOIN 
    user_expenses ON user_expenses.user_id = users.id
WHERE 
    user_expenses.description NOT LIKE "%free%"
GROUP BY 
    user_expenses.user_id
HAVING 
    COUNT(*) = 1

但是,当然,这会产生以下问题:

  

SELECT列表不在GROUP BY子句中,并且包含非聚合列&app; user.expenses.created_at'它在功能上不依赖于GROUP BY子句中的列;这与sql_mode = only_full_group_by

不兼容

将此列添加到group_by是有问题的,因为它实际上会返回具有不同描述的多个费用的用户。

有人可以就如何解决这个问题提出一些建议吗?我只希望用户在user_expenses表中只有一个条目,无论描述的类型如何。

2 个答案:

答案 0 :(得分:1)

您可以进行虚拟聚合。变化:

user_expenses.created_at, user_expenses.description

select列表中:

min(user_expenses.created_at) created_at, min(user_expenses.description) description

...这与原始值相同,因为您知道每组只有一个。

通过users.id字段进行分组也更为自然,因为它允许外部加入user_expenses表(如果你需要的话):

group by users.id

注意:在MySql 5.7+中,没有必要聚合functionally dependent on the grouped-by fields的字段。由于users记录的所有字段都由users.id值确定,因此它们可以不进行聚合。

答案 1 :(得分:1)

您可以执行子查询,也可以伪聚合不在列表中的值:

(1):

SELECT users.id, users.email, users.stripe_plan, users.previous_plan, users.created_at, user_expenses.created_at, user_expenses.description
FROM users
INNER JOIN user_expenses
ON user_expenses.user_id = users.id
WHERE user_expenses.description NOT LIKE "%free%"
and users.id not in
  (select ue2.user_id from user_expenses ue2 group by user_id having count(*) > 1)

(2)

SELECT users.id, max(users.email), max(users.stripe_plan), max(users.previous_plan), max(users.created_at), max(user_expenses.created_at), max(user_expenses.description)
FROM users
INNER JOIN user_expenses
ON user_expenses.user_id = users.id
WHERE user_expenses.description NOT LIKE "%free%"
GROUP BY user_expenses.user_id
HAVING COUNT(*) = 1