代码之家  ›  专栏  ›  技术社区  ›  xenoid

选择列值唯一的记录

sql
  •  0
  • xenoid  · 技术社区  · 6 年前

    我在论坛上有一张帖子表( mybb_posts ,与 username 海报)。

    我希望所有帖子都是由只发布过一次的人发布的,换句话说,所有的行 用户名 用户名 列。

    到目前为止,我使用这个:

    SELECT *
    FROM mybb_posts
    WHERE username IN
        (SELECT username
         FROM
           (SELECT username,
                   count(*) COUNT
            FROM `mybb_posts`
            GROUP BY username) tbl1
         WHERE COUNT=1)
    

    但这三个嵌套的SELECT看起来很难看。

    有没有更优雅/高效/简单的方法?我在SO和其他地方看到的所有答案都集中在获取唯一的id上。

    这是针对MySQL数据库的,如果你想建议非标准解决方案(但首选标准解决方案)。

    1 回复  |  直到 6 年前
        1
  •  3
  •   Gordon Linoff    6 年前

    用户名列中用户名仅出现一次的所有行。

    这表明窗口功能:

    SELECT p.*
    FROM (SELECT p.*, COUNT(*) OVER (PARTITION BY p.username) as cnt
          FROM mybb_posts p
         ) p
    WHERE cnt = 1;
    

    注意:您的版本不需要两个嵌套子查询。您可以使用 HAVING 条款:

    SELECT p.*
    FROM mybb_posts p
    WHERE p.username IN (SELECT p2.username
                         FROM mybb_posts p2
                         GROUP BY p2.username
                         HAVING COUNT(*) = 1
                        );
    
        2
  •  1
  •   GMB    6 年前

    我能想到的最便携的解决方案是 not exists 以及相关子查询。这适用于大多数数据库,包括那些不支持窗口功能的数据库(如MySQL 5.x版本或MS Access)。这也应该是一个相当有效的选择。

    为此,您的表中需要一个主键。假设它被调用 post_id ,即:

    select p.*
    from mybb_posts p
    where not exists (
        select 1
        from mybb_posts p1
        where p1.username = p.username and p1.post_id <> p.post_id
    )
    

    为了提高性能,您需要一个索引 (username, post_id) .