繁体   English   中英

聚合中最大值的计数 select

[英]Count of the max value in an aggregate select

我想计算特定字段中最小值的最大值的数量。

如果我取消注释这些行,则此 select 已损坏:

select clientnumber
      ,count(distinct clientname) as NumberUnique
      ,max(clientname) as UniqueSample1
      -- ,sum(case clientname when min(clientname) then 1 else 0 end) as UniqueCount1
      ,min(clientname) as UniqueSample2
      -- ,sum(case clientname when min(clientname) then 1 else 0 end) as UniqueCount2
  FROM dbo.InvoicesSent dt
 group by clientnumber
 having count(distinct clientname) > 1

背景:我们正在审查同一客户编号的发票上有两个不同名称的记录。 知道两者中哪一个的计数更高有助于分析。

注意:我知道还有其他解决方案可以考虑超过 2 个唯一值,但在这一点上,我想解决这个问题的学术价值。 我也知道我可以通过子选择来解决这个问题,但我坚持要一些优雅的解决方案。

如果您知道有两个名称,那么您可以在没有子选择的情况下执行此操作:

select top (1) with ties clientnumber, 
       min(clientname) over (partition by clientnumber) as min_name,
       max(clientname) over (partition by clientnumber) as max_name,
       (case when clientname = min(clientname) over (partition by clientnumber)
             then count(*)
             else sum(count(*)) over (partition by clientnumber) - count(*)
        end) as min_count,
       (case when clientname = max(clientname) over (partition by clientnumber)
             then count(*)
             else sum(count(*)) over (partition by clientnumber) - count(*)
        end) as max_count
from InvoicesSent i
group by clientnumber, clientname
order by row_number() over (partition by clientnumber order by clientname) +
         (case when min(clientname) over (partition by clientnumber) = max(clientname) over (partition by clientnumber) then 1 else 0 end);

我并不是说这很优雅。 只是根据您的条件是可能的。

这是一个稍微简单的形式:

select top (1) with ties clientnumber, 
       clientname as min_name,
       max(clientname) over (partition by clientnumber) as max_name,
       count(*) as min_count,
       sum(count(*)) over (partition by clientnumber) - count(*) max_count
from InvoicesSent i
group by clientnumber, clientname
order by row_number() over (partition by clientnumber order by clientname) +
         (case when count(*) over (partition by clientnumber) >= 2 then 0 else 1 end)

还有一个db<>fiddle

其实,这并没有那么糟糕。 它按名称列和客户端聚合,使用 window 函数将所有数据放在一行上,然后选择一行。 仅对具有多个名称order by有一个小技巧。

如果您正在使用支持 string_agg 的 sql 服务器,则可以执行以下操作

这是一个 db fiddle 链接https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=4184c994d37e0dc7178212cd657ba15f

create table invoices(id int identity, clientnumber int, clientname varchar(100));

insert into invoices(clientnumber,clientname)
select t.clientnumber,clientname
  from (values(100,'Adam')
             ,(100,'Adam')
             ,(100,'Abraham')
             ,(101,'Grace')
             ,(101,'Grace')
             ,(102,'Paul')
       )t(clientnumber,clientname);



select clientnumber
      ,string_agg(concat(clientname,'-',cnt),';') as clientname_and_cnt
 from(     
select distinct
       clientnumber
      ,clientname
      ,count(*) over(partition by clientnumber,clientname) as cnt
  from invoices
     )x
group by clientnumber     
order by 2 desc

Output
+--------------+--------------------+
| clientnumber | clientname_and_cnt |
+--------------+--------------------+
|          102 | Paul-1             |
|          101 | Grace-2            |
|          100 | Abraham-1;Adam-2   |
+--------------+--------------------+

如果你想通过 clientnumber 显示那些有两个或多个客户名的,那么在 having 子句中添加以下内容

having(charindex(';',string_agg(concat(clientname,'-',cnt),';')))<>0

如果您想根据客户名称的发票数量订购,那么您也可以执行以下操作(在组子句中)

select clientnumber
      ,string_agg(concat(clientname,'-',cnt),';') within group(order by cnt desc) as clientname_and_cnt
 from(     
select distinct
       clientnumber
      ,clientname
      ,count(*) over(partition by clientnumber,clientname) as cnt
  from invoices
     )x
group by clientnumber     
order by 2 desc

暂无
暂无

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

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