【问题标题】:How to count rows on joined table without WHERE [duplicate]如何在没有 WHERE 的情况下计算联接表上的行数 [重复]
【发布时间】:2020-01-10 03:29:02
【问题描述】:

我有两个相关的表 usersnetworks — 对应用户的社交媒体帐户。帐户(网络)可能是这样的:facebook、linkedin、youtube、vimeo 等...

每个用户都可以拥有零个或多个社交媒体帐户(在 networks 表中)。

就我而言,我需要计算每个用户的仅视频帐户(youtube 和/或 vimeo)。

我正在尝试这两个查询:

SELECT users.email, COUNT(networks.network) as video_networks_counter,
FROM users
LEFT JOIN networks ON networks.user_id = users.id
WHERE networks.network='youtube' OR networks.network='video'
GROUP BY users.id

SELECT users.email, 
CASE networks.network WHEN 'youtube' THEN 1 ELSE 0 END as video_networks_counter,
CASE networks.network WHEN 'vimeo' THEN 1 ELSE 0 END as video_networks_counter
FROM users
LEFT JOIN networks ON networks.user_id = users.id
GROUP BY users.id

这不能按预期工作。

第一个查询的问题是用户不能有任何网络,但他也必须在一个计数器为 0 的列表中。所以WHERE 条件在我的情况下似乎没用。

CASE 的第二次查询也不起作用。

【问题讨论】:

  • WHERE 子句上的相等条件指的是带有LEFT OUTER JOIN 的第二个表,使得它实际上是INNER JOIN
  • 了解 LEFT JOIN ON 返回的内容:INNER JOIN ON rows UNION ALL 不匹配的左表行,由 NULL 扩展。作为 OUTER JOIN 的一部分,始终知道您想要什么 INNER JOIN。 WHERE 或 INNER JOIN ON 在 OUTER JOIN ON 删除任何由 NULL 扩展的行后,需要右 [sic] 表列不为 NULL,即只留下 INNER JOIN ON 行,即“将 OUTER JOIN 转换为 INNER JOIN”。你有那个。
  • 这是一个常见问题解答。在考虑发布之前,请始终在谷歌上搜索任何错误消息和许多清晰、简洁和准确的问题/问题/目标的措辞,带或不带您的特定字符串、名称和行号以及带和不带“site:stackoverflow.com”并阅读很多点击和答案。如果您发布问题,请使用一个短语作为标题。请参阅How to Ask 和投票箭头鼠标悬停文本。
  • 请在代码问题中给出minimal reproducible example--剪切&粘贴&运行代码;具有所需和实际输出(包括逐字错误消息)的示例输入(作为表格初始化代码);标签和版本;明确的规范和解释。这包括您可以提供的最少代码,即您显示的代码可以通过您显示的代码扩展为不正常。 (调试基础。) PS“不起作用”并没有告诉我们任何事情。使用足够多的单词、句子和对部分示例的引用来清楚完整地表达你的意思。请在每个帖子中提出一个问题。

标签: mysql sql join count case


【解决方案1】:

将条件移至on 子句:

SELECT u.email, COUNT(n.network) as video_networks_counter
FROM users u LEFT JOIN
     networks n
     ON n.user_id = u.id AND
        n.network IN ('youtube', 'video')
GROUP BY u.email;

注意事项:

  • 您的WHERE 子句将外连接变为内连接,因为NULL 值不匹配。
  • 对于此类比较,INOR 子句更简单。
  • GROUP BY 键应与SELECT 中的未聚合列匹配。
  • 表别名使查询更易于编写和阅读。
  • 您可能打算使用'vimeo' 而不是'video'

而且,如果你想分别计算它们:

SELECT u.email, COUNT(n.network) as video_networks_counter,
       SUM( n.network = 'youtube') as num_youtube,
       SUM( n.network = 'vimeo') as num_vimeo           
FROM users u LEFT JOIN
     networks n
     ON n.user_id = u.id AND
        n.network IN ('youtube', 'vimeo')
GROUP BY u.email;

【讨论】:

    【解决方案2】:

    在您的第一个查询中设置 ON 子句中的条件并删除 WHERE:

    SELECT users.email, COUNT(networks.network) as video_networks_counter,
    FROM users
    LEFT JOIN networks ON networks.user_id = users.id
    AND (networks.network='youtube' OR networks.network='video')
    GROUP BY users.id
    

    您的 WHERE 子句会删除所有没有帐户的用户,从而使 LEFT JOIN 无用。

    【讨论】:

      【解决方案3】:

      你可以总结一下你的情况有多频繁

      SELECT u.email, 
             SUM(n.network IN ('youtube', 'video')) as video_networks_counter,
      FROM users u
      LEFT JOIN networks n ON n.user_id = u.id
      GROUP BY u.email
      

      【讨论】:

        【解决方案4】:

        您可以使用 CASE 和 SUM 尝试此选项-

        SELECT users.email, 
        SUM(
            CASE 
                WHEN networks.network='youtube' OR networks.network='video' THEN 1 
                ELSE 0 
            END
        ) as video_networks_counter,
        FROM users
        LEFT JOIN networks ON networks.user_id = users.id
        GROUP BY users.email
        

        【讨论】:

          猜你喜欢
          • 2022-10-13
          • 1970-01-01
          • 2013-01-30
          • 1970-01-01
          • 2016-08-14
          • 1970-01-01
          • 1970-01-01
          • 2012-07-13
          • 2020-09-16
          相关资源
          最近更新 更多