Search code examples
sqlmysqlexcept

Query for Users not in a specific group? (Wanted to use EXCEPT but it seems MySQL doesn't support it)


I have a many to many relationship between users and groups:

CREATE TABLE IF NOT EXISTS `SecurityIdentifiers` (
  `Guid` char(36) NOT NULL,
  PRIMARY KEY  (`Guid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE IF NOT EXISTS `CaseIdUsers` (
  `Sid` char(36) NOT NULL,
  `Acl` int(11) NOT NULL,
  `FirstName` varchar(45) NOT NULL,
  `LastName` varchar(45) NOT NULL,
  `CaseID` varchar(8) NOT NULL,
  PRIMARY KEY  (`Sid`),
  UNIQUE KEY `CaseID_UNIQUE` (`CaseID`),
  KEY `fk_CaseIDUsers_AccessControlLists1` (`Acl`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE IF NOT EXISTS `GroupMembers` (
  `User` char(36) NOT NULL,
  `Group` char(36) NOT NULL,
  PRIMARY KEY  (`User`,`Group`),
  KEY `fk_Groups_has_SecurityIdentifiers_SecurityIdentifiers1` (`User`),
  KEY `fk_Groups_has_SecurityIdentifiers_Groups1` (`Group`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE IF NOT EXISTS `Groups` (
  `Sid` char(36) NOT NULL,
  `Acl` int(11) NOT NULL,
  `Name` varchar(45) NOT NULL,
  `Description` varchar(255) NOT NULL,
  PRIMARY KEY  (`Sid`),
  UNIQUE KEY `Name_UNIQUE` (`Name`),
  KEY `fk_Groups_Access Control Lists1` (`Acl`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

I need to find all the users who aren't in a specific group. I wanted to do something like:

SELECT CaseId FROM CaseIdUsers
EXCEPT
SELECT CaseId FROM CaseIdUsers
JOIN GroupMembers ON GroupMembers.User = CaseIdUsers.Sid
JOIN Groups ON GroupMembers.Group = Groups.Sid
WHERE Groups.Name = 'MyGroupName'

But MySQL doesn't support EXCEPT. What do I do now?


Solution

  • You can use a NOT IN(), or a <> ANY()

    SELECT CaseId
    FROM CaseIdUsers
    WHERE CaseID NOT IN (
      SELECT CaseId 
      FROM CaseIdUsers
        JOIN GroupMembers ON GroupMembers.User = CaseIdUsers.Sid
        JOIN Groups ON GroupMembers.Group = Groups.Sid
      WHERE Groups.Name = 'MyGroupName'
    )
    

    Alternatively, you can use a LEFT JOIN with a GROUP BY

    SELECT CaseId 
    FROM CaseIdUsers
      LEFT JOIN GroupMembers ON GroupMembers.User = CaseIdUsers.Sid
      LEFT JOIN Groups ON GroupMembers.Group = Groups.Sid
        AND Groups.Name = 'MyGroupName'
    HAVING COUNT(Groups.Sid) = 0