【问题标题】:Could I put a condition to filter my COUNT clause? mysql我可以设置一个条件来过滤我的 COUNT 子句吗? mysql
【发布时间】:2012-10-02 02:29:36
【问题描述】:

我将仅解释与问题相关的内容,并省略任何其他不相关的细节。

现状:

我有两张桌子,硬币和用户。

coin有三个字段id, uid, fid. 币表关联了用户(已经在系统中注册并可以邀请好友)和他们的好友(已经接受邀请并成为会员)-该表仅存储被邀请后成功注册-

id是唯一索引。
uid是存储用户id。
fid是存储好友ID(接受邀请并成为系统成员的好友)。

users 包含有关用户的常用信息,例如 id, fname, lname, email ...etc 和 date_create

目标: 查找发出最多邀请的获奖者。换一种说法。 要查找邀请次数最多的顶级用户及其被邀请的朋友必须在 2012-08-31 之前注册。日期存储在表“用户”列 date_create 中。日期格式为 yyyy-mm-dd

例子-

Table coin

    id uid fid 
    1  333 777   
    2  444 888       
    3  555 999       
    4  333 123         
    5  444 456         
    6  333 789   

Table users
    id   date_create
    333  2012-07-15
    444  2012-07-20
    555  2012-07-25
    777  2012-07-25
    888  2012-07-25
    999  2012-10-02   <-- I don't need this to be counted
    123  2012-07-25
    456  2012-07-25
    789  2012-07-25

表示用户 333 的邀请数量最多(邀请了 3 个用户)-> 777,123 和 789 用户 444 邀请了 2 个用户,用户 555 只邀请了 1 个用户,但是对于 555,由于他的朋友(999)在 2012-08-31 之后注册,所以不会被计算在内

我想要的是用户

333 has made 3 invitations before 2012-08-31. 
444 has made 2 invitations before 2012-08-31.

到目前为止我所做的是:[完全不确定]

SELECT
  c.uid,       
  u.fname,
  u.lname,
  u.phone,
  u.email,
  u.country,
  COUNT(c.fid)    AS NoOfFriends
FROM coin AS c
  JOIN users AS u
    ON c.uid = u.id
GROUP BY c.uid
ORDER BY NoOfFriends desc

这个查询带来(据我所知)邀请最多的用户,无论他/她的朋友何时注册。

所以我的问题是: Q1) 如何将日期条件应用到我的查询中?

我想要拥有最多好友邀请的用户。他/她邀请的朋友必须在2012-08-31之前接受邀请并注册。在该日期之后任何其他接受的邀请都不应计算在内。

请提供代码示例。

【问题讨论】:

  • 你的问题不是很清楚。与其同时问两个问题,不如只问一个问题会更清楚。如果你有两个问题,然后选择一个,然后先问那个。如果您仍然需要更多帮助,您可以稍后再创建一个问题。让你的每一个问题都清晰、准确和独立,避免一次混淆多个问题,否则你只会混淆自己和其他人。
  • 删除了第一个问题。感谢您的评论。
  • "用户必须在 2012 年 10 月 31 日之前注册" 哪个表包含注册日期以及列的名称是什么?
  • 在表 'users' 列 date_create.
  • 这与您最初提出的问题完全不同。或者你的问题太糟糕了,以至于无法从你最初写的内容中猜出你想要什么。请花一些时间改进您的问题,使其与您在 cmets 中所写的内容相匹配。 请在问题中包含您想要的结果集。 考虑编写一个 SQL fiddle。用 SQL 提琴写一个好问题可能要多花 10 分钟,但如果你一开始就这样做了,那么你现在已经有了答案。

标签: mysql database select count conditional-statements


【解决方案1】:

这是我的回答,感谢所有尝试并提供帮助的人,尤其是 LastCoder 迅速提供了实际解决方案。

SELECT
  c.uid,
  info.id,
  info.fname,
  info.lname,
  info.phone,
  info.email,
  info.country,
  COUNT(DISTINCT c.fid) AS NoOfFriends   -- modified this to get unique invitations
FROM coin c
  JOIN users AS friends
    ON c.fid = friends.id
  LEFT JOIN users AS info
    ON c.uid = info.id
WHERE friends.date_create < '20120831'
GROUP BY c.uid
ORDER BY NoOfFriends DESC
LIMIT 10

老实说,我没有使用其他解决方案,因为我不清楚SUM(CASE WHEN ...)。

【讨论】:

    【解决方案2】:

    很多答案让实际用户和受邀朋友感到困惑。

    SELECT
        c.uid
    info.fname,
    info.lname,
    info.phone,
    info.email,
    info.country,
    info.date_create,
        COUNT(c.fid) AS [NoOfFriends]
    FROM coin AS c
        JOIN users AS friend
            ON c.fid = friend.id
        LEFT JOIN users AS info
            ON c.uid = info.id
    WHERE friend.date_create < '20121031'
    GROUP BY c.uid
    

    EDIT修正数据格式

    【讨论】:

    • 没错。 +1 表示“很多答案将实际用户与受邀朋友混淆”。每次我尝试获取日期时,我都会得到用户创建日期而不是邀请朋友的日期。
    • 使用文化特定的日期格式不值得投反对票,但它几乎是......除非您在查询中专门设置语言/日期格式,否则您应该使用文化非特定格式@987654322 @ 因为无法将其转换为不正确/无效的日期。
    • @GarethD - 技术上正确是最好的正确。我会吞下我对我们的自豪感,并使用与文化无关的日期格式。
    • 你的答案比其他人的答案要简单得多,所以通过这个,我会从 info 中获取获奖者的详细信息,而friend 会将每个成员的朋友数计算为 uid。谢谢。
    • 顺便说一句,你为什么把 NoOfFriends 放在方括号之间?还有一件事,我将 COUNT 修改为 COUNT(DISTINCT c.fid),因为事实证明有些用户多次发送了多个邀请。
    【解决方案3】:

    您仅按c.uid 分组的方法在 MySQL 中有效,但您将无法使用其他 RDBMS。

    在这种情况下,我会将计数移至子查询,在我看来它更易于阅读,并且它很好地将查询与您要应用的逻辑分开,即获取朋友在之前注册的所有邀请特定日期,然后加入到邀请他们的用户。

    SELECT  u.ID,
            u.fname,
            u.lname,
            u.phone,
            u.email,
            u.country,
            u.`date_create`,
            COALESCE(FriendCount, 0) AS FriendCount
            COALESCE(FriendCount2, 0) AS FriendCount2
    FROM    users AS u
            LEFT JOIN  
            (   SELECT  coin.UID,
                        COUNT(coind.fid) AS FriendCount,
                        COUNT(CASE WHEN Users.Date_Create < '20121031' THEN coind.fid END) AS FriendCount2
                FROM    coin
                        INNER JOIN Users
                            ON coin.FID = users.ID
                GROUP BY coin.UID
            ) c
                ON c.uid = u.id
    ORDER BY FriendCount2 DESC
    

    如果您不关心好友总数,只关心 10 月 31 日之前的好友,那么您可以将其简化为

    SELECT  u.ID,
            u.fname,
            u.lname,
            u.phone,
            u.email,
            u.country,
            u.`date_create`,
            COALESCE(FriendCount, 0) AS FriendCount
    FROM    users AS u
            LEFT JOIN  
            (   SELECT  coin.UID,
                        COUNT(coind.fid) AS FriendCount
                FROM    coin
                        INNER JOIN Users
                            ON coin.FID = users.ID
                WHERE   Users.Date_Create < '20121031'
                GROUP BY coin.UID
            ) c
                ON c.uid = u.id
    ORDER BY FriendCount DESC
    

    【讨论】:

      【解决方案4】:

      count(expression) 函数计算该表达式的结果不为空的行。如果表达式只返回 true 或 false,所有行都将被计算在内,因为 true 和 false 都不为空。

      要使用带有计数的表达式,您必须使其在 false 时返回 null:

       COUNT(friend.date_create < '2012-10-31' or null) AS NoOfFriends
      

      【讨论】:

      • 但是 date_create 在另一个字段中?计数将如何访问两个表并检查。需要根据uid从coin中获取fid,然后在users中查看date_create来获取fid,如果date在20120831之前就应该算进去,否则就移动到与该uid相关的下一个fid。
      【解决方案5】:

      您可以将SUM 与CASE 结合使用:

      SUM(CASE WHEN <cond> THEN 1 ELSE 0 END) as NoOfFriends
      

      完整的语句如下所示:

      SELECT
        c.uid,
        u.fname,
        u.lname,
        u.phone,
        u.email,
        u.country,
        u.`date_create`,
        SUM(CASE WHEN f.date_create < 2012-10-31 THEN 1 ELSE 0 END)    AS NoOfFriends
      FROM coin AS c
        JOIN users AS u
          ON c.uid = u.id
        join users as f
          on c.fid = f.id
      GROUP BY c.uid, u.fname, u.lname, u.phone, u.email, u.country, u.`date_create`
      ORDER BY NoOfFriends desc
      

      【讨论】:

      • 这里还有一点值得一提的是,您可以在 group 子句之后使用 HAVING 子句来过滤“NoOfFriends”。 (仅针对那些不知道这一点的人)SUM/CASE 组合是我非常喜欢和使用的东西。
      • 您也可以将其简化为SUM(&lt;cond&gt;),因为布尔条件的计算结果为 1 或 0,尽管我认为这可能是 MySQL 对 SQL 的扩展。
      • @Barmar:确实,这是一个 MySql 扩展。例如,它在 Oracle 中不起作用。
      猜你喜欢
      • 1970-01-01
      • 2012-10-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-10
      • 2012-08-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多