简体   繁体   中英

Get count With Distinct in SQL Server

Select
Count(Distinct iif(t.HasReplyTask = 1, t.CustomerID, Null)) As Reply,
Count(Distinct iif(t.HasOverdueTask = 1, t.CustomerID, Null)) As Overdue,
Count(Distinct t.CustomerID) As Total
From 
Table1 t 

If a customer is in Reply, we need to remove that customer in Overdue count, That means if Customer 123 is in both, The Overdue count should be one less. How can I do this?

I am adding some data here, Customer 123 has "HasReplyTask", so, we have to filter that customer from Count in OverDue(even though that customer has one Overdue task without HasReplyTask). 234 is one and Distinct of 456 is one. So, the overdue count should be 2, Above query returns 3

数据

If I've got it right, this can be done using a subquery to get the numbers for each customer, and then get the summary information as follows:

Select Sum(HasReplyTask) As Reply, 
       Sum(HasOverdueTask) As Overdue,
       Count(CustomerID) As Total
From (
Select CustomerID, 
       IIF(Max(Cast(HasReplyTask As TinyInt))<>0, 0, Max(Cast(HasOverdueTask As TinyInt))) As HasOverdueTask,
       Max(Cast(HasReplyTask As TinyInt)) As HasReplyTask
From Table1
Group by CustomerID) As T

I don't know about column data types, so I used cast function to use max function.

db<>fiddle

Reply Overdue Total
1 2 3

Add t.HasReplyTask != 1 to your second count:

Select
    Count(Distinct iif(t.HasReplyTask = 1, t.CustomerID, Null)) As Reply,
    Count(Distinct iif(t.HasReplyTask != 1 AND t.HasOverdueTask = 1, t.CustomerID, Null)) As Overdue,
    Count(Distinct t.CustomerID) As Total
From 
    Table1 t 

What would probably be more efficient for you is to pre-aggregate your table by customer ID and have counts per customer. Then your outer query can test for whatever you are really looking for. Something like

select
      sum( case when PQ.ReplyCount > 0 then 1 else 0 end ) UniqReply,
      sum( case when PQ.OverdueCount > 0 then 1 else 0 end ) UniqOverdue,
      sum( case when PQ.OverdueCount - PQ.ReplyCount > 0 then 1 else 0 end ) PendingReplies,
      count(*) as UniqCustomers
   from
      ( select 
              yt.customerid,
              count(*) CustRecs,
              sum( case when yt.HasReplyTask = 1 then 1 else 0 end ) ReplyCount,
              sum( case when yt.HasOverdueTask = 1 then 1 else 0 end ) OverdueCount
           from
              yourTable yt
           group by
              yt.customerid ) PQ

Now to differentiate the count you are REALLY looking for, you might need to do a test against the prequery (PQ) of ReplyCount vs OverdueCount such as... For a single customer ID (thus the pre query), if the OverdueCount is GREATER than the ReplyCount, then it is still considered overdue? So for customer 123, they had 3 overdue, but only 2 replies. You want that counted once? But for customers 234 and 456, the only had overdue entries and NO replies. So, the total where Overdue - Reply > 0 = 3 distinct people.

Is that your ultimate goal?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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