两列上的多个条件与order by

时间:2015-05-11 05:30:24

标签: php mysql

我有3张桌子

Users (Table1)
---------------------------
id      username    enabled
1       user1           1
2       user2           1
3       user3           1
4       user4           1

Packages (Table2)
---------------------------
id      package_type
1       lead
2       featured

Subscription (Table3)
---------------------------
id      user_id     package_id      enabled
1           1           1               1
2           1           2               1
3           2           1               0  <- user2 don't have lead package active
4           2           2               1
5           3           1               1
6           4           1               1
7           4           2               1

查询以创建表格并插入上面的数据

CREATE TABLE `users`( `id` INT(11) NOT NULL AUTO_INCREMENT, `username` VARCHAR(255), `enabled` TINYINT(1) NOT NULL DEFAULT 1, PRIMARY KEY (`id`) ); 
CREATE TABLE `packages`( `id` INT(11) NOT NULL AUTO_INCREMENT, `package_type` VARCHAR(255), PRIMARY KEY (`id`) ); 
CREATE TABLE `subscription`( `id` INT(11) NOT NULL AUTO_INCREMENT, `user_id` INT(11) NOT NULL, `package_id` INT(11) NOT NULL, `enabled` TINYINT(1) NOT NULL DEFAULT 1, PRIMARY KEY (`id`), FOREIGN KEY (`user_id`) REFERENCES `users`(`id`), FOREIGN KEY (`package_id`) REFERENCES `packages`(`id`) ); 

INSERT INTO `packages` (`package_type`) VALUES ('lead') , ('featured'); 
INSERT INTO `users` (`username`) VALUES ('user1'), ('user2'), ('user3'), ('user4');
INSERT INTO `subscription` (`user_id`, `package_id`, `enabled`) VALUES ('1', '1', '1'), ('1', '2', '1'), ('2', '1', '0'), ('2', '2', '1'), ('3', '1', '1'), ('4', '1','1'), ('4', '2','1') ;

我已经测试了这个需要修改的示例查询

SELECT 
  u.id,
  p.package_type,
  u.username,
  u.enabled,
  RAND() AS random
FROM 
  users u
  LEFT JOIN subscription s ON u.id = s.user_id
  LEFT JOIN packages p ON s.package_id = p.id  
WHERE 
  u.enabled = 1 AND s.enabled = 1  
-- GROUP BY u.id 
ORDER BY p.package_type ASC  , random ASC

,输出

id  package_type  username  enabled               random  
 1  featured      user1           1     0.1285319878985472
 2  featured      user2           1    0.14050112477550388  <- user2 don't have lead package active so should not show up in result
 4  featured      user4           1    0.15676092836704192
 1  lead          user1           1     0.2874740681494345
 3  lead          user3           1     0.3382110375335543
 4  lead          user4           1     0.8286330139531131

预期产出

id  package_type  username  enabled               random  
 1  featured      user1           1     0.1285319878985472
 4  featured      user4           1    0.15676092836704192     
 3  lead          user3           1     0.3382110375335543     

此输出应符合这些条件

  1. 仅显示主动包激活的用户
  2. 如果用户还有精选套餐,那么特色用户会在输出中排在第一位

2 个答案:

答案 0 :(得分:2)

您可以根据条件GROUP_CONCATSUBSTRING_INDEX使用直接内部联接来显示结果集中的精选包,以便首先使用SUM(p.id = 2)对已排序的用户进行排序特色包装首先显示

SELECT 
  u.id,
SUBSTRING_INDEX(  
  GROUP_CONCAT(p.package_type ORDER BY p.`id` DESC),',',1
  ) package_type,
  u.username,
  u.enabled
FROM 
  users u
   JOIN subscription s ON u.id = s.user_id
   JOIN packages p ON s.package_id = p.id  
WHERE 
  u.enabled = 1 AND s.enabled = 1
  GROUP BY u.`id`
  HAVING SUM(p.id = 1) > 0
  ORDER BY SUM(p.id = 2) DESC  ,RAND()

DEMO

答案 1 :(得分:1)

您可以通过两次查询获得所需的结果,并unioning结果。

select q.user_id, q.package_type, u.username, q.enabled, rand() from (
select 1 as t, s.user_id, p.package_type, s.enabled 
  from subscriptions s
    inner join packages p
      on s.package_id = p.id
  where p.package_type = 'featured'
    and s.enabled = 1
    and exists 
      (select 1
        from subscriptions ss
          inner join packages pp on ss.package_id = pp.id
        where ss.enabled = 1
          and pp.package_type = 'lead'
          and ss.user_id = s.user_id
      )
union all
select 2 as t, s.user_id, p.package_type, s.enabled
  from subscriptions s
    inner join packages p
      on s.package_id = p.id
   where not exists
     (select 1 
       from subscriptions ss
         inner join packages pp on ss.package_id = pp.id
        where ss.enabled = 1
          and pp.package_type = 'featured'
          and ss.user_id = s.user_id
     )
     and p.package_type = 'lead'
     and s.enabled = 1
) q
inner join users u
  on q.user_id = u.id
order by t asc

demo here

第一个查询会获得所有拥有有效潜在客户包和功能包的用户,并返回其精选包。

第二个查询会获得所有拥有有效潜在客户包但没有功能包的用户,并返回其潜在客户包。

每个查询都有一个标识符t,以确定它是否为特色或主要包结果,然后我们按此排序。