MySQL从联接表中选择查询,该查询具有确切的子行数

时间:2018-10-25 01:55:37

标签: mysql doctrine

我有两个下表。

PermissionAccessEntities


peID      |   petID
-------------------
1         |   1
2         |   4
3         |   1
4         |   2
5         |   4
6         |   4
-------------------

PermissionAccessEntityGroups


pegID     |   peID     |  gID
-----------------------------
1         |   5        |  1
2         |   5        |  2
3         |   5        |  3
4         |   6        |  2
5         |   6        |  3
-----------------------------

现在我有一个getOne的学说,如下所示-

select pae.peID from PermissionAccessEntities pae 
left join PermissionAccessEntityGroups paeg1 on pae.peID = paeg1.peID 
left join PermissionAccessEntityGroups paeg2 on pae.peID = paeg2.peID 
where petID = 4 and paeg1.gID = 2 and paeg2.gID = 3;

哪个返回56。但是我想得到具有匹配行的确切数量的结果。在这种情况下为6

是否可以使用JOIN获取与上述相同的结果集?

非常感谢您的帮助。

3 个答案:

答案 0 :(得分:2)

    在这种情况下,
  • Where条件将无济于事。因为,您要考虑所有行的计数以进行进一步过滤。您将需要使用Group By子句将Having与条件过滤一起使用。
  • 我们还可以简化查询,使其仅对PermissionAccessEntityGroups表使用一个联接。
  • Count()函数用于计算组中的行数。我们还可以使用Sum( conditional statements )对符合条件的行数进行计数。条件语句将为匹配的行返回1,对于不匹配的行返回0。

请尝试以下查询:

SELECT pae.peID 
FROM PermissionAccessEntities AS pae 
LEFT JOIN PermissionAccessEntityGroups AS paeg 
  ON pae.peID = paeg.peID 
WHERE pae.petID = 4
GROUP BY pae.peID
HAVING COUNT(*) = SUM(paeg.gID IN (2,3))

DB Fiddle DEMO


现在,请记住Count(NULL) = 0;但是COUNT(0) = COUNT(1) = 1。因此,仅使用Count()函数编写此查询的另一种方法是:

SELECT pae.peID 
FROM PermissionAccessEntities AS pae 
LEFT JOIN PermissionAccessEntityGroups AS paeg 
  ON pae.peID = paeg.peID 
WHERE pae.petID = 4
GROUP BY pae.peID
HAVING COUNT(*) = COUNT(CASE WHEN paeg.gID IN (2,3) THEN 1 END)

DB Fiddle DEMO 2

答案 1 :(得分:2)

您可以通过首先查找与(2,3)匹配的条目,然后查看其中是否还有一个与其他值之一匹配,来获得所需的结果。完全不匹配(paeg2.peID IS NULL)的任何匹配项:

SELECT DISTINCT(pae.peID)
FROM PermissionAccessEntities pae 
JOIN PermissionAccessEntityGroups paeg1 ON paeg1.peID = pae.peID AND paeg1.gID IN (2,3)
LEFT JOIN PermissionAccessEntityGroups paeg2 ON paeg2.peID = pae.peID AND paeg2.gID NOT IN (2,3)
WHERE pae.petID = 4 AND paeg2.peID IS NULL

Demo on dbfiddle

答案 2 :(得分:0)

SELECT pae.peID FROM PermissionAccessEntities pae 
INNER JOIN PermissionAccessEntityGroups paeg1 ON  pae.peID=paeg1.peID
WHERE pae.petID = 4 AND paeg1.peID NOT IN (SELECT DISTINCT peID FROM 
PermissionAccessEntityGroups WHERE gID NOT IN (2,3));