【问题标题】:SQL to gather data from one table while counting records in anotherSQL 从一个表中收集数据,同时计算另一个表中的记录
【发布时间】:2011-07-06 15:30:31
【问题描述】:

我有一个用户表和一个歌曲表,我想选择用户表中的所有用户,同时计算他们在歌曲表中有多少首歌曲。我有这个 SQL 但它不起作用,有人能发现我做错了什么吗?

SELECT jos_mfs_users.*, COUNT(jos_mfs_songs.id) as song_count 
FROM jos_mfs_users 
INNER JOIN jos_mfs_songs
ON jos_mfs_songs.artist=jos_mfs_users.id

非常感谢您的帮助。谢谢!

【问题讨论】:

  • 在什么情况下不起作用?它会给出错误,还是只是意外结果?
  • 我猜每条记录的歌曲数是 1。

标签: sql count


【解决方案1】:

内连接不起作用,因为它将歌曲表中的每个匹配行与用户表连接。

SELECT jos_mfs_users.*, 
    (SELECT COUNT(jos_mfs_songs.id) 
        FROM jos_mfs_songs
        WHERE jos_mfs_songs.artist=jos_mfs_users.id) as song_count 
FROM jos_mfs_users 
WHERE (SELECT COUNT(jos_mfs_songs.id) 
        FROM jos_mfs_songs
        WHERE jos_mfs_songs.artist=jos_mfs_users.id) > 10

【讨论】:

  • 感谢您的帮助,这行得通。如果我想在 WHERE 子句中使用 song_count 怎么办,因为当我设置 WHERE song_count > 10 时,它不起作用。我如何引用 song_count 值。非常感谢您的帮助!
  • 使用HAVINGCOUNT 等聚合进行比较
  • 您可以将 (SELECT COUNT()...) 子句添加到 WHERE 语句中。我将对其进行编辑以显示这一点。你也可以试试“have”子句。
  • SELECT A.*, (SELECT COUNT(*) FROM B WHERE B.a_id = A.id) AS TOT FROM A 是一个更简单的解决方案
【解决方案2】:

缺少GROUP BY 子句,例如

SELECT jos_mfs_users.id, COUNT(jos_mfs_songs.id) as song_count 
FROM jos_mfs_users 
INNER JOIN jos_mfs_songs
ON jos_mfs_songs.artist=jos_mfs_users.id
GROUP BY jos_mfs_users.id

如果您想在选择列表中添加来自jos_mfs_users 的更多列,您也应该将它们添加到GROUP BY 子句中。

【讨论】:

    【解决方案3】:

    变化:

    • 不要SELECT *...指定你的字段。我包括了 ID 和 NAME,您可以根据需要添加更多,但也可以将它们放在 GROUP BY

    • 更改为LEFT JOIN - INNER JOIN 不会列出任何没有歌曲的用户

    • 添加了GROUP BY,所以它给出了一个有效的计数并且是有效的语法

      SELECT u.id, u.name COUNT(s.id) as song_count 
      FROM jos_mfs_users AS u
      LEFT JOIN jos_mfs_songs AS S
          ON s.artist = u.id
      GROUP BY U.id, u.name
      

    【讨论】:

      【解决方案4】:

      试试

      SELECT 
        *, 
        (SELECT COUNT(*) FROM jos_mfs_songs as songs WHERE songs.artist=users.id) as song_count 
      FROM 
        jos_mfs_users as users
      

      【讨论】:

        【解决方案5】:

        这似乎是多对多的关系。我的意思是看起来每个用户的用户表中可以有几条记录,他们拥有的每首歌曲中的一条。 我会有三张桌子。
        用户,每个用户有一条记录
        歌曲,每首歌都有一个记录
        USER_SONGS,每个用户/歌曲组合都有一条记录
        现在,您可以通过对中间表进行查询来计算每个用户拥有的歌曲。您还可以了解有多少用户拥有一首特定的歌曲。

        这会告诉你每个用户有多少首歌曲

        select id, count(*) from USER_SONGS
        GROUP BY id;
        

        这会告诉你每首歌有多少用户

        select artist, count(*) from USER_SONGS
        GROUP BY artist;
        

        我确定您需要根据自己的需要对此进行调整,但它可能会为您提供所需的结果类型。

        您还可以将这些查询中的任何一个连接到其他两个表以查找用户名和/或艺术家姓名。

        HTH
        哈夫萨瑟

        ps 我不确定您是在寻找歌曲数量还是艺术家数量。

        【讨论】:

          【解决方案6】:

          您需要一个GROUP BY 子句才能使用聚合函数(例如COUNT()

          所以,假设 jos_mfs_users.id 是主键,这样的事情会起作用:

          SELECT jos_mfs_users.*, COUNT( jos_mfs_users.id ) as song_count 
          FROM jos_mfs_users 
          INNER JOIN jos_mfs_songs
            ON jos_mfs_songs.artist = jos_mfs_users.id
          GROUP BY jos_mfs_users.id
          

          注意

          • 由于您是按用户 ID 分组的,因此结果中每个不同的用户 ID 都会得到一个结果
          • COUNT() 需要的是被分组的行数(在这种情况下是每个用户的结果数)

          【讨论】:

          • -1 对于单个字段上的 SELECT *GROUP BY - 如果他的 SQL 引擎甚至允许,他将获得每个 users.id 的随机记录(大多数不会)
          • 这将如何返回随机记录?对于按 jos_mfs_users.id 分组的每个结果行,来自 jos_mfs_users 的所有字段都是相同的! jos_mfs_songs 中没有字段是 SELECTed(只有一个 COUNT())。我认为你错了!
          • 你是假设所有其他字段将是相同的。 OP 没有表明它是一个独特的字段或 PK。 选择不在您的GROUP BY 或聚合中的字段是应避免的反模式。 句号。
          • 好吧,你是对的。我已经编辑了答案以陈述我的假设。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-10-31
          • 1970-01-01
          • 1970-01-01
          • 2021-01-26
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多