加入Group By&在MySQL中使用Case进行排序

时间:2016-02-28 15:24:26

标签: mysql join group-by sql-order-by case

为什么这个查询不起作用?它是否因为按顺序和组合而被组合?

一个表是广告,其他是订阅,第三个是服务,第四个是服务和位置之间的多对多关系(位置是应该显示广告的位置)。

我想要的是首先订购存储在位置2的广告表中的广告,然后定位那些没有定位位置然后位置1的广告(此订单是生成programmicaly的)

广告表:
id ,name,subscription_id

订阅表:
subscription_id ,service_id,日期,付费等...

service_locations表:
service_id location_id

你可以在这种情况下有第四张表,但它并不重要


查询:

select adverts.id, GROUP_CONCAT(service_locations.location_id) AS locations from adverts 
    left join subscriptions 
        on adverts.subscription_id = subscriptions.id
    left join service_locations 
        on service_locations.service_id = subscriptions.service_id
    group by adverts.id
    order by case service_locations.location_id 
        when 2 then 1 
        when 1 then 3 
        else 2 
    end


预期结果:

+----+-----------+
| id | locations |
+----+-----------+
|  1 | 2         |
|  3 | 1,2       |
|  2 | null      |
+----+-----------+


我真正得到的是(行中的第三个有位置2,但是它放在null之后):

+----+-----------+
| id | locations |
+----+-----------+
|  1 | 2         |
|  2 | null      |
|  3 | 1,2       |
+----+-----------+

2 个答案:

答案 0 :(得分:0)

使用group by时,group by以外的所有列都应具有聚合功能。所以,我认为你打算这样的事情:

select a.id, GROUP_CONCAT(sl.location_id) AS locations
from adverts a left join
     subscriptions s
     on a.subscription_id = s.id left join
     service_locations sl
     on sl.service_id = s.service_id
group by a.id
order by max(case sl.location_id 
               when 2 then 1 
               when 1 then 3 
               else 2 
             end);

我不确定max()是否真的需要,但你确实需要聚合功能。这特别产生了问题中的输出:

order by (case min(sl.location_id)
               when 2 then 1 
               when 1 then 2
               else 3
           end);

答案 1 :(得分:0)

我找到了一个解决方案,order by必须在group by之前执行,这不是默认行为,更多关于这个行为:https://stackoverflow.com/a/14771322/4329156)(必须使用子查询)

因此,查询应该看起来像

select *, GROUP_CONCAT(location_id) as locations from (
    select adverts.id AS id, service_locations.location_id AS location_id from adverts 
    left join subscriptions 
        on adverts.subscription_id = subscriptions.id
    left join service_locations 
        on service_locations.service_id = subscriptions.service_id
    order by case service_locations.location_id 
        when 2 then 1 
        when 1 then 3 
        else 2 
    end
    ) as table 
    group by table.id
    order by case table.location_id 
        when 2 then 1 
        when 1 then 3 
        else 2 
    end