我有两张桌子:
Members:
id username
Trips:
id member_id flag_status created
("YES" or "NO")
我可以这样做一个查询:
SELECT
Trip.id, Trip.member_id, Trip.flag_status
FROM
trips Trip
WHERE
Trip.member_id = 1711
ORDER BY
Trip.created DESC
LIMIT
3
哪个可以给出这样的结果:
id member_id flag_status
8 1711 YES
9 1711 YES
10 1711 YES
我的目标是知道会员的最后三次旅行是否都有一个flag_status =“YES”,如果三个中的任何一个!=“是”,那么我不想让它算在内。
我还希望能够删除WHERE Trip.member_id = 1711子句,让它为所有成员运行,并给我最后3次旅行都有flag_status =“YES”的成员总数
有什么想法吗?
谢谢!
http://sqlfiddle.com/#!2/28b2d
在那个sqlfiddle中,当我正在寻找的正确查询运行时,我应该看到如下结果:
COUNT(Member.id)
2
应该符合资格的两名成员是成员1和3.成员5失败,因为他的一次旅行有flag_status =“NO”
答案 0 :(得分:2)
您可以使用GROUP_CONCAT函数,以升序获取按ID排序的所有状态的列表:
SELECT
member_id,
GROUP_CONCAT(flag_status ORDER BY id DESC) as status
FROM
trips
GROUP BY
member_id
HAVING
SUBSTRING_INDEX(status, ',', 3) NOT LIKE '%NO%'
然后使用SUBSTRING_INDEX,您只能提取最后三个状态标志,并排除那些包含NO的状态标志。请参阅小提琴here。我假设您的所有行都按ID排序,但如果您有创建日期,则最好使用:
GROUP_CONCAT(flag_status ORDER BY created DESC) as status
正如雷蒙德建议的那样。然后,您还可以使用以下内容返回返回行的计数:
SELECT COUNT(*)
FROM (
...the query above...
) as q
答案 1 :(得分:2)
虽然我喜欢fthiella解决方案的简单性,但我想不出一个在很大程度上依赖于数据表示的解决方案。为了不依赖它,你可以做这样的事情:
SELECT COUNT(*) FROM (
SELECT member_id FROM (
SELECT
flag_status,
@flag_index := IF(member_id = @member, @flag_index + 1, 1) flag_index,
@member := member_id member_id
FROM trips, (SELECT @member := 0, @flag_index := 1) init
ORDER BY member_id, id DESC
) x
WHERE flag_index <= 3
GROUP BY member_id
HAVING SUM(flag_status = 'NO') = 0
) x
小提琴here。注意我稍微修改了小提琴以删除其中一个用户。
该过程基本上根据每个成员id desc
对每个成员的行程进行排名,然后仅保留最后3个成员。然后它确保所提取的行程中没有一个在flag_status中有NO
。最后计算所有匹配的会员。