【问题标题】:MySQL Query to find row duplicates based on condition with limitMySQL Query 根据限制条件查找行重复项
【发布时间】:2013-11-21 13:37:45
【问题描述】:

我有两张桌子:

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",如果三个中的任何一个 != "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"

【问题讨论】:

  • 在 SQLfiddle 上放置一个包含示例数据的表,还包含 multble member_ids..
  • "我的目标是知道该成员的最后三趟行程是否都有 flag_status = "YES",如果这三个中的任何一个 != "YES",那么我不希望它计算在内。 "您的意思是,MySQL 应该始终根据日期(DESC)检查最后一条记录,并在 flag_status = "Yes" 上过滤这三个记录,还是我误解了那部分..
  • member_id 是 members 表的外键,且 members 表中的 username 和 id 是唯一的。
  • 所有三个都必须等于 YES 才能将该用户包含在 COUNT 中。
  • 我不明白你的 cmets anwsers 是如何挖掘的......

标签: mysql duplicates limit conditional-statements rows


【解决方案1】:

您可以使用 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

【讨论】:

  • 谢谢你!通过将您的一行修改为: SUBSTRING_INDEX(status, ',', 3) = "YES,YES,YES" 我能够让它按我的意愿运行!
  • @user2278120 不客气 :) 是的,几乎是一样的,使用“YES,YES,YES”你将返回所有具有至少三个状态标志的成员,使用 NOT LIKE '%NO% ' 它还会选择只有一两个“YES”的记录
  • 不明白为什么这被标记为正确,因为这是假设 id 而不是基于 created(topicstarter 想要所以这是偶然的结果是正确的,因为很可能是 AUTO_INCREMENT id.. )。应该是GROUP_CONCAT(flag_status ORDER BY created DESC) as status
  • @RaymondNijland 我没有注意到创建的专栏,我已经更新了我的答案,tnx
  • @thiella 没问题 +1 破解 GROUP_CONCAT 这样的函数
【解决方案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。最后,所有匹配的成员都被计算在内。

【讨论】:

  • 您好,Mosty,感谢您的回复,但是即使您的解释,我也无法理解。您能否为使用 mySQL 变量的新手更深入地解释一下?我确实想针对我的实际数据库运行它,看看它是否比 fthiella 的解决方案更快,根据哪个更快,我会选择合适的一个以获得最佳答案。
  • 如果您需要有关 UDV 的更多信息,您应该阅读诸如 this one 之类的教程
  • 谢谢。 :) 我会检查的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-29
  • 2018-10-31
  • 2021-12-27
  • 2020-07-01
  • 2016-02-27
  • 2015-12-18
相关资源
最近更新 更多