繁体   English   中英

MySQL:按值计算记录,然后用计数更新另一列

[英]MySQL: count records by value and then update another column with their count

三个非常相关的SQL问题(我实际上使用的是mySQL):

假设一个人员表有两列名称,国家

1)我如何向有同胞的人展示? 我可以按国家显示公民人数:

select country, count(*) as fellow_citizens 
from people 
group by country

但是我似乎无法显示其中fellow_citizens> 1的记录。以下内容无效:

select name, country, count(*) as fellow_citizens 
from people 
group by country 
where fellow_citizens > 1;

......因为我不想把人分组,所以不会是我想要的任何方式。

2)为了解决上述问题,我有了将fellow_citizens存储在新列中的想法。 这听起来像是MySQL等问题的变体:从一个表中计算记录然后更新另一个表 不同之处在于我想更新同一个表。

但是那里给出的答案在这里不起作用:

update people as dest 
set fellow_citizens = 
    (select count(*) from people as src where src.country = dest.country);

我收到此错误消息:

您不能在FROM子句中为更新指定目标表'dest'

看来我需要通过另一个临时表来做到这一点。 可以在没有临时表的情况下完成吗?

3)作为上述的变体,如何按国家/地区更新人员列? 我发现我可以通过以下方式更新全局计数器:

set @i:=0; update people set counter = @i:=@i+1 order by country;

但是,当国家的价值发生变化时,我想重置我的@i计数器。

有没有办法在mySQL中做到这一点而不需要完整的程序代码?

1 - >

select country, count(*) as fellow_citizens 
from people 
group by country 
having fellow_citizens > 1

对不起,但不能真正理解第2点和第3点。

您的选择查询应如下所示:

SELECT name, country, count(*) as fellow_citizens  
FROM people  
GROUP BY country  
HAVING fellow_citizens > 1; 

推荐解决方案
你不想分组,你只想重复每个人的计数。
这些数据没有规范化,像这样的代码不是一个很好的方法。
但是,以下选择将为您提供所有人及其计数:

SELECT p.* 
     , s.fellow_citizens
FROM people p
INNER JOIN (
  SELECT country, count(*) as fellow_citizens
  FROM people  
  GROUP BY country  
  HAVING count(*) > 1) s ON (s.country = p.country)

如果您不想要实际计数,只需来自拥有1个以上公民的国家的人,另一种方式来编写此查询(这可能比以前的方法更快,您必须使用您的数据进行测试):

SELECT p.* 
FROM people p
WHERE EXISTS
      ( SELECT *
        FROM people p2  
        WHERE p2.country = p.country 
          AND p2.PK <> p.PK         -- the Primary Key of the table 
      )

只有在你面临缓慢的情况下才能这样做
如果你想使用更新语句将计数包含在表中,我建议你使用一个单独的计数表,因为至少有一些规范化。

INSERT INTO people_counts (country, pcount)
  SELECT p.country, count(*) as peoplecount
  FROM people p
  GROUP BY p.country
ON DUPLICATE KEY pcount = VALUES(pcount)

然后,您可以将计数表与人员数据一起加速选择。

SELECT p.*, c.pcount
FROM people p
INNER JOIN people_counts c ON (p.country = c.country)

你有没有尝试过这个问题

select name, fellow_citizens
from people left join  
(select country, count(*) as fellow_citizens  
 from people group by country  
 having fellow_citizens > 1) as citizens  
 on people.country = citizens.country  

我不是很擅长编写sql查询; 但我认为这可以解决你的问题

我会这样做的。

create view citizencount as
select country, count(*) citizens 
from people 
group by country 

然后您的查询变为(类似的东西)

select p.personid, p.country, cc.citizens -1 fellow_citizens
from people p
join citizencount cc on
  cc.country = p.country

您可能想要添加

where fellow_citizens > 0

暂无
暂无

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

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