代码之家  ›  专栏  ›  技术社区  ›  F.P

SQL搜索尚未分组的条目

  •  1
  • F.P  · 技术社区  · 14 年前

    我有两张桌子:

    +------- IPs ------+  +---- Groups ---+
    | Id (Int)         |  | Id (Int)      |
    | IP (String)      |  | Name (String) |
    | Comment (String) |  | IPs (String)  |
    +------------------+  +---------------+
    

    IPs -列 Groups 是一个以逗号分隔的IP列表,该组由以下IP组成: Id IP地址

    我现在想找到所有 IP地址 Group s -现场。

    我的想法是以某种方式加入所有 Groups.IPs 一起寻找所有的 IPs.IP

    我真的很想完全用SQL来完成(编程方式不是问题)。

    1 回复  |  直到 14 年前
        1
  •  3
  •   Community Dan Abramov    7 年前

    我相信有一些黑客的解决方案可以解决您的问题,但是如果您想“完全在SQL中完成这个任务”,我建议重构您的表以避免使用逗号分隔的id列表。对于逗号分隔字段引起的问题列表,我建议查看最近的堆栈溢出帖子:

    我建议使用如下所示的表模式:

    CREATE TABLE ips (
       id int,
       ip varchar(255),
       comment varchar(255),
       PRIMARY KEY (id)
    );
    
    CREATE TABLE groups (
       id int,
       name varchar(255),
       PRIMARY KEY (id)
    );
    
    CREATE TABLE ip_groups (
       group_id int,
       ip_id int,
       PRIMARY KEY (ip_id, group_id),
       FOREIGN KEY (group_id) REFERENCES ips(id),
       FOREIGN KEY (ip_id) REFERENCES groups(id)
    );
    

    那么您的查询就可以这么简单:

    SELECT * 
    FROM   ips
    WHERE  NOT EXISTS (SELECT id 
                       FROM ip_groups 
                       WHERE ip_groups.ip_id = ips.id);
    

    例子:

    INSERT INTO ips VALUES (1, '127.0.0.1', 'localhost');
    INSERT INTO ips VALUES (2, '10.0.0.1', 'router');
    INSERT INTO ips VALUES (3, '10.0.0.100', 'my macbook');
    
    INSERT INTO groups VALUES (1, '10.0.0 subnet');
    INSERT INTO groups VALUES (2, 'computers');
    
    INSERT INTO ip_groups VALUES (1, 2);
    INSERT INTO ip_groups VALUES (1, 3);
    INSERT INTO ip_groups VALUES (2, 3);
    

    +----+-----------+-----------+
    | id | ip        | comment   |
    +----+-----------+-----------+
    |  1 | 127.0.0.1 | localhost |
    +----+-----------+-----------+
    1 row in set (0.00 sec)
    

    127.0.0.1


    SELECT     ips.id, ips.ip, ips.comment
    FROM       ips
    LEFT JOIN  ip_groups ON (ip_groups.ip_id = ips.id)
    WHERE      ip_groups.group_id IS NULL;
    

    这通常比以前的解决方案快,因为它不使用 correlated subquery . 相关子查询的问题是,它们对于外部查询中的每一行执行一次,因此当外部查询( SELECT * FROM ips 在本例中)返回许多行。