简体   繁体   English

获取联接表中只有1个匹配行的记录?

[英]Getting records which have only 1 matching row in the joined table?

Consider the following tables: 请考虑以下表格:

Persons  
|id   |firstname|lastname|  
|-----|---------|--------|  
|1    |John     |Doe     |  
|2    |Jim      |Smith   |  
|3    |Jane     |Boggard |  
|4    |Joe      |Dash    |  

Licences
|p_id |licence|
|-----|-------|
|1    |car    |
|1    |bike   |
|2    |car    |
|3    |car    |
|3    |bike   |
|1    |plane  |
|4    |bike   |

How can I get the persons who have only 1 associated row in the licences table and which the value is "car" ? 如何获得许可证表中只有1个关联行且值为“ car”的人员? (in our case: Jim Smith) (在我们的案例中:吉姆·史密斯)

Thanks 谢谢

The first part of your question is pretty easy (getting a person with only 1 associated row in the licenses table). 问题的第一部分非常简单(在licenses表中得到一个只有1个关联行的人)。 You just do a GROUP BY , and then HAVING COUNT(*) = 1 : 您只需执行GROUP BY ,然后拥有HAVING COUNT(*) = 1

select
    persons.id
  ,persons.firstname
  ,Persons.lastname
from Persons
    inner join Licenses on
        Licenses.p_id = Persons.`id`
group by
    persons.id
    ,persons.firstname
    ,persons.lastname
having 
  count(*) = 1

The second part of your question is a little tricker: For the people with only 1 license, which have a car license. 问题的第二部分有些棘手:对于只有1个驾照且拥有驾照的人。 To do this, you can apply the filter to the HAVING clause, so it's applied after the group by . 为此,您可以将过滤器应用于HAVING子句,因此该过滤器将在group by之后应用。 For example (note the new last line): 例如(注意最后一行):

select
    persons.id
  ,persons.firstname
  ,Persons.lastname
from Persons
    inner join Licenses on
        Licenses.p_id = Persons.`id`
group by
    persons.id
    ,persons.firstname
    ,persons.lastname
having 
  count(*) = 1
  and min(licenses.licence) = 'car'

You're using the MIN function because you generally need to apply aggregate functions in the HAVING clause. 您正在使用MIN函数,因为通常需要在HAVING子句中应用聚合函数。 However, since you already know that all these people only have 1 license, the MIN doesn't really make a difference (you could even use MAX with the same results). 但是,由于您已经知道所有这些人仅拥有1个许可证,因此MIN并没有真正的不同(您甚至可以使用MAX获得相同的结果)。

This should help to illustrate the process... 这应该有助于说明该过程...

SELECT p.*, SUM(l.licence = 'car') cars, COUNT(*) total
  FROM persons p
  JOIN licences l
    ON l.p_id = p.id
 GROUP
    BY p.id;
   +----+-----------+----------+------+-------+
   | id | firstname | lastname | cars | total |
   +----+-----------+----------+------+-------+
   |  1 | John      | Doe      |    1 |     3 |
   |  2 | Jim       | Smith    |    1 |     1 |
   |  3 | Jane      | Boggard  |    1 |     2 |
   |  4 | Joe       | Dash     |    0 |     1 |
   +----+-----------+----------+------+-------+

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM