# SQL在分区上计数不同

10

MyTable

``````Col_A | Col_B
A     | 1
A     | 1
A     | 2
A     | 2
A     | 2
A     | 3
b     | 4
b     | 4
b     | 5``````

``````Col_A   | Col_B | Result
A       | 1     | 3
A       | 1     | 3
A       | 2     | 3
A       | 2     | 3
A       | 2     | 3
A       | 3     | 3
b       | 4     | 2
b       | 4     | 2
b       | 5     | 2``````

``````select *,
count (distinct col_B) over (partition by col_A) as 'Result'
from MyTable``````

18

``````SELECT      *
FROM        #MyTable AS mt
CROSS APPLY (   SELECT COUNT(DISTINCT mt2.Col_B) AS dc
FROM   #MyTable AS mt2
WHERE  mt2.Col_A = mt.Col_A
-- GROUP BY mt2.Col_A
) AS ca;``````

`GROUP BY`考虑到问题中提供的数据，该子句是多余的，但可以为您提供更好的执行计划。请参阅后续Q＆A CROSS APPLY产生外部联接

6

``````select col_a, col_b, max(rnk) over (partition by col_a)
from (
select col_a, col_b
, dense_rank() over (partition by col_A order by col_b) as rnk
from #mytable
) as t    ``````

6

``````SELECT
Col_A,
Col_B,
DistinctCount = DENSE_RANK() OVER (PARTITION BY Col_A ORDER BY Col_B ASC )
+ DENSE_RANK() OVER (PARTITION BY Col_A ORDER BY Col_B DESC)
- 1
- CASE COUNT(Col_B) OVER (PARTITION BY Col_A)
WHEN COUNT(  *  ) OVER (PARTITION BY Col_A)
THEN 0
ELSE 1
END
FROM
dbo.MyTable
;``````

``````  DENSE_RANK() OVER (PARTITION BY Col_A ORDER BY Col_B ASC )
+ DENSE_RANK() OVER (PARTITION BY Col_A ORDER BY Col_B DESC)
- 1``````

``````SELECT
Col_A,
Col_B,
DistinctCount = DENSE_RANK() OVER (PARTITION BY Col_A ORDER BY Col_B ASC )
+ DENSE_RANK() OVER (PARTITION BY Col_A ORDER BY Col_B DESC)
- CASE COUNT(Col_B) OVER (PARTITION BY Col_A)
WHEN COUNT(  *  ) OVER (PARTITION BY Col_A)
THEN 1
ELSE 2
END
FROM
dbo.MyTable
;``````

2
``````create table #MyTable (
Col_A varchar(5),
Col_B int
)

insert into #MyTable values ('A',1)
insert into #MyTable values ('A',1)
insert into #MyTable values ('A',2)
insert into #MyTable values ('A',2)
insert into #MyTable values ('A',2)
insert into #MyTable values ('A',3)

insert into #MyTable values ('B',4)
insert into #MyTable values ('B',4)
insert into #MyTable values ('B',5)

;with t1 as (

select t.Col_A,
count(*) cnt
from (
select Col_A,
Col_B,
count(*) as ct
from #MyTable
group by Col_A,
Col_B
) t
group by t.Col_A
)

select a.*,
t1.cnt
from #myTable a
join t1
on a.Col_A = t1.Col_a``````

1

``````--ignore the existence of nulls
SELECT [mt].*, [Distinct_B].[Distinct_B]
FROM #MyTable AS [mt]

INNER JOIN(
SELECT [Col_A], COUNT(DISTINCT [Col_B]) AS [Distinct_B]
FROM #MyTable
GROUP BY [Col_A]
) AS [Distinct_B] ON
[mt].[Col_A] = [Distinct_B].[Col_A]
;``````

``````--customizable null handling
SELECT [mt].*, [Distinct_B].[Distinct_B]
FROM #MyTable AS [mt]

INNER JOIN(
SELECT

[Col_A],

(
COUNT(DISTINCT [Col_B])
/*
--uncomment if you also want to count Col_B NULL
--as a distinct value
+
MAX(
CASE
WHEN [Col_B] IS NULL
THEN 1
ELSE 0
END
)
*/
)
AS [Distinct_B]

FROM #MyTable
GROUP BY [Col_A]
) AS [Distinct_B] ON
[mt].[Col_A] = [Distinct_B].[Col_A]
/*
--uncomment if you also want to include Col_A when it's NULL
OR
([mt].[Col_A] IS NULL AND [Distinct_B].[Col_A] IS NULL)
*/``````