2017-03-02 1 views
0

I했습니다 다음 데이터 세트 다음 계산에SQL 서버 - 계산 총 여과 값

Machine Type Value 
1  A 11 
1  B 32 
2  A 23 
3  A 1 
4  B 23 
4  B 31 
5  B 56 
6  A 12 

그리고 내가 원하는 : 그것을 할 수있는 가장 좋은 방법은

SELECT COUNT(WHERE TYPE = A)/COUNT(TOTAL) 
FROM.... 

? 등을 사용하고 있습니다 :

DECLARE @CNT INT 
SET @CNT = (SELECT COUNT(*) FROM dataset) 
SELECT COUNT(*)/CNT 
FROM dataset 
WHERE TYPE = A 

을하지만이있는 경우 큰 쿼리가 느린 SQL을두고이 계산을 위해 동일한 쿼리를 반복 ... 누구나 더 나은 솔루션을 제공 할 수 있습니까?

답변

1

조건 집계를 사용하여 : http://rextester.com/GXN95560

create table t (Machine int, Type char(1), Value int) 
insert into t values 
(1,'A',11) 
,(1,'B',32) 
,(2,'A',23) 
,(3,'A',1) 
,(4,'B',23) 
,(4,'B',31) 
,(5,'B',56) 
,(6,'A',12) 

select sum(case when type='a' then 1.0 else 0 end)/count(*) 
from t 

수익률 : 1.0를 합산하는 것은 당신에게 int 테스트 설정

select sum(case when type='a' then 1.0 else 0 end)/count(*) 
from t 

0 또는 1로 변환되지 않는 비율을 줄 것이다 0.500000

SELECT COUNT(case when TYPE = 'a' then 1 end)/COUNT(*) 
FROM t 

반환 : 0

2

조건부 계산을 수행하려면 case 표현식을 사용하십시오.

(때 type <> acase는 null를 돌려줍니다 count()을 널 (null)을 계산하지 않습니다.).

SELECT COUNT(case when TYPE = A then 1 end) * 1.0/COUNT(*) 
FROM dataset 

편집 : 나는 몇 가지 성능 테스트를 실행하기로 결정 다른 답변에서 영감을

. 여기에 사용 된 테이블 tx는 수십만 개의 행을가집니다. c2 열에는 색인이 생성되며 테이블 전체에 무작위로 배치 된 수백 개의 다른 값이 있습니다.

쿼리 1 :

select count(case when c2 = 'A' then 1 end) * 1.0/count(*) from tx; 

Direct I/O count  :  83067 
Buffered I/O count :   0 
Page faults   :   3 
CPU time  (seconds):  77.18 
Elapsed time (seconds):  77.17 

쿼리 2

select avg(case when c2 = 'A' then 1.0 else 0.0 end) from tx; 

Direct I/O count  :  83067 
Buffered I/O count :   0 
Page faults   :   0 
CPU time  (seconds):  84.90 
Elapsed time (seconds):  84.90 

쿼리 3

select (select count(*) from tx where c2 = 'A') * 1.0/
      (select count(*) from tx) 
from onerow_table; 

Direct I/O count  :  86204 
Buffered I/O count :   0 
Page faults   :   2 
CPU time  (seconds):  3.45 
Elapsed time (seconds):  3.45 

PS. MS SQL Server에서는 실행되지 않습니다.

+0

어쩌면'COUNT (링크를 찾을 수 없습니다) 목표 테이블에 존재하지 않는 A 나 B는 'SUM'을 사용하여 첫 번째 'COUNT'를 대체 할 수 있습니까? – LONG

+0

@LONG COUNT는 괜찮습니다. 그러나 정수로 나눈 정수이기 때문에 모든 유형이 A 인 경우 항상 0 또는 1을 반환합니다.1을 1.0으로 바꾸면 고칠 수 있습니다. –

+0

아, 알겠습니다. '/'연산을 위해서도 역시 문제라고 생각합니다.) – LONG

0
select 
cast((sum(case when Type='A' then 1 else 0 end)) as float)/cast(Count(Type)) as float) 
from dataset 
1

다음은 고든이 몇 주 전에 설명했던 약간의 트릭입니다. (유형은 다음 한 끝을 = 할 때 경우)`실제로 총 수의 값이 1 열 또는에서 오는 기대하고있다

Declare @YourTable table (Machine int, Type char(1), Value int) 
insert into @YourTable values 
(1,'A',11) 
,(1,'B',32) 
,(2,'A',23) 
,(3,'A',1) 
,(4,'B',23) 
,(4,'B',31) 
,(5,'B',56) 
,(6,'A',12) 

select avg(case when type='a' then 1.0 else 0 end) 
from @YourTable 

반환

0.500000 
+0

분명히 나는 ​​이것이 최상의 해결책이라고 생각한다.) –

+0

@ GordonLinoff 나는 우아함을 사랑한다. 부끄러워 결코 전에 나를 알 수 없었다. –