mysql 返回选定组中某个值的计数和其他组中某个值的计数的SQL

lx0bsm1f  于 2023-04-10  发布在  Mysql
关注(0)|答案(3)|浏览(133)

我有下面的表格:

create table tablex (fileID int, file varchar(10), name varchar(10));
insert into tablex (fileID, file, name) values (1, 'file1' , 'AAA'),(1, 'file1' , 'AAA'),(1, 'file1' , 'AAA'),(2, 'file2' , 'AAA'),(2, 'file2' , 'AAA'),(2, 'file2' , 'AAA'),(1, 'file1' , 'BBB'),(1, 'file1' , 'BBB'),(2, 'file2' , 'BBB'),(2, 'file2' , 'BBB'),(3, 'file3' , 'BBB'),(3, 'file3' , 'BBB'),(1, 'file1' , 'CCC'),(1, 'file1' , 'CCC');

tablex

fileID | file | name
1 | file1 | AAA
1 | file1 | AAA
1 | file1 | AAA
2 | file2 | AAA
2 | file2 | AAA
2 | file2 | AAA
1 | file1 | BBB
1 | file1 | BBB
2 | file2 | BBB
2 | file2 | BBB
3 | file3 | BBB
3 | file3 | BBB
1 | file1 | CCC
1 | file1 | CCC

我希望只获取出现在多个文件中的名称,然后计算在具有最大id的文件中出现的次数,以及在其他文件中出现的次数。
AAA -文件2中出现3次,其他文件中出现3次
BBB -文件3中出现2次,其他文件中出现4次
我正在尝试使用窗口函数(仍在学习),但不确定这种方法是否是最好的方法,因为我必须添加一个独特的使其工作

select distinct t.name, count(t.name) over (partition by t.name) countAll,
       count(t.name) over (partition by t.name, fileId) countLatestFile,
       count(t.name) over (partition by t.name) - count(t.name) over (partition by t.name, fileId) countOthers
  from tablex t
  join (select name from tablex group by name having count(distinct fileId)  > 1) tdups
   on t.name = tdups.name;

还有其他想法吗

vdzxcuhz

vdzxcuhz1#

使用窗口函数dense_rank,如下所示:
首先使用cte根据fileID按等级排列名称。使用cte2(具有最大等级)从每个名称中获取最新文件。
然后,我们连接两个CTE以产生所需的结果:

with cte as (
  select *, dense_rank() over (partition by name order by fileID) rn,
           count(name) over (partition by name) countAll
  from tablex
),
cte2 as (
  select name, max(rn) max_rn
  from cte
  group by name
  having max(rn) > 1
)
select c.name, max(c.countAll) as countAll, max(c.file) as latestFile, count(c.name) as countLatestFile, 
       max(c.countAll) - count(c.name) as countOthers
from cte c
inner join cte2 c2 on c.rn = c2.max_rn and c.name = c2.name
group by c.name

Demo here

ulydmbyx

ulydmbyx2#

您可以使用max window函数和条件聚合,如下所示:

with max_ids as
(
  select *,
    max(fileID) over (partition by name) maxid
  from tablex
)
select name,
       count(*) countAll,
       sum(fileID = maxid) countLatestFile,
       sum(fileID <> maxid) countOthers
from max_ids 
group by name
having count(distinct fileId)  > 1

See demo

zf9nrax1

zf9nrax13#

不使用窗口函数也能做到的:

select name,
(select max(fileId) 
from tablex
where name=t.name) as max_fileid,
count(case when fileid= (select max(fileId) 
                        from tablex
                        where name=t.name)
            then 1
        end) as count_for_max_fileid,
count(case when fileid != (select max(fileId) 
                        from tablex
                        where name=t.name)
            then 1
        end)as count_for_other
from tablex t
where name in (select name from tablex group by name having count(distinct fileid)>1)
group by name
;

-- result set:
+------+------------+----------------------+-----------------+
| name | max_fileid | count_for_max_fileid | count_for_other |
+------+------------+----------------------+-----------------+
| AAA  |          2 |                    3 |               3 |
| BBB  |          3 |                    2 |               4 |
+------+------------+----------------------+-----------------+

相关问题