复杂查询具有多个用户的表

时间:2015-03-17 19:16:04

标签: mysql database select join subquery

我有一张这样的表:

score
id  week  status
1    1     0
2    1     1
3    1     0
4    1     0
1    2     0
2    2     1
3    2     0
4    2     0
1    3     1
2    3     1
3    3     1
4    3     0

除了第3周,我希望获得所有星期状态为零的所有人的身份。这样的事情:

结果:

result:
id   w1.status  w2.status  w3.status
1    0          0          1
3    0          0          1

我有这个查询,但在较大的数据集上效率非常低。

SELECT w1.id, w1.status, w2.status, w3.status
FROM
(SELECT s.id, s.status
FROM score s 
WHERE s.week = 1) w1
LEFT JOIN
(SELECT s.id, s.status
FROM score s 
WHERE s.week = 2) w2 ON w1.id=w2.id
LEFT JOIN
(SELECT s.id, s.status
FROM score s 
WHERE s.week = 3) w3 ON w1.id=w3.id
WHERE w1.status=0 AND w2.status=0 AND w3.status=1

我正在寻找一种更有效的计算方法。

4 个答案:

答案 0 :(得分:0)

您可以使用not exists作为

select 
t1.id, 
'0' as `w1_status` , 
'0' as `w2_status`, 
'1' as `w3_status` 
from score t1 
where 
t1.week = 3 
and t1.status = 1 
and not exists( 
  select 1 from score t2 
  where t1.id = t2.id and t1.week <> t2.week and  t2.status  = 1
);

为了获得更好的性能,您可以在表格中添加索引

alter table score add index week_status_idx (week,status);

答案 1 :(得分:0)

如果是静态周数(1-3),group_concat可能会被用作黑客..

概念:

SELECT
    id,
    group_concat(status) as totalStatus
    /*(w1,w2=0,w3=1 always!)*/
FROM
    tableName
WHERE
    totalStatus = '(0,0,1)' /* w1=0,w2=1,w3=1 */
GROUP BY
    id
ORDER BY 
    week ASC

(写在旅途中。未经测试)

答案 2 :(得分:0)

SELECT p1.id, p1.status, p2.status, p3.status
FROM score p1 
JOIN score p2 ON p1.id = p2.id
JOIN score p3 ON p2.id = p3.id
WHERE p1.week = 1
AND p1.status = 0
AND p2.week = 2
AND p2.status = 0
AND p3.week = 3
AND p3.status = 1

试试这个,应该有效

答案 3 :(得分:0)

select id
from score
where week in (1, 2, 3)
group by id
having sum(
    case
        when week in (1, 2) and status = 0 then 1
        when week = 3 and status = 1 then 1
        else 0
    end
) = 3

或更普遍......

select id
from score
group by id
having
        sum(case when status = 0 then 1 else 0 end) = count(*) - 1
    and min(case when status = 1 then week else null end) = max(week)