[SQL] 추가 (별개의) 필터를 집계 열
SQL추가 (별개의) 필터를 집계 열
예상대로이 코드는 작동하지만 그것은 길고 오싹합니다.
select p.name, p.played, w.won, l.lost from
(select users.name, count(games.name) as played
from users
inner join games on games.player_1_id = users.id
where games.winner_id > 0
group by users.name
union
select users.name, count(games.name) as played
from users
inner join games on games.player_2_id = users.id
where games.winner_id > 0
group by users.name) as p
inner join
(select users.name, count(games.name) as won
from users
inner join games on games.player_1_id = users.id
where games.winner_id = users.id
group by users.name
union
select users.name, count(games.name) as won
from users
inner join games on games.player_2_id = users.id
where games.winner_id = users.id
group by users.name) as w on p.name = w.name
inner join
(select users.name, count(games.name) as lost
from users
inner join games on games.player_1_id = users.id
where games.winner_id != users.id
group by users.name
union
select users.name, count(games.name) as lost
from users
inner join games on games.player_2_id = users.id
where games.winner_id != users.id
group by users.name) as l on l.name = p.name
당신이 볼 수 있듯이, 그것은 검색을위한 3 개 반복적 인 부분으로 구성되어 있습니다 :
그리고 그 각각은 2 개 부분으로 구성되어 있습니다 :
이것은 어떻게 단순화 할 수 있을까?
그 결과 외모가 너무 좋아 :
name | played | won | lost
---------------------------+--------+-----+------
player_a | 5 | 2 | 3
player_b | 3 | 2 | 1
player_c | 2 | 1 | 1
해결법
-
==============================
1.포스트 그레스 9.4 이상에서 집계 FILTER 절은 짧고 빠른 :
포스트 그레스 9.4 이상에서 집계 FILTER 절은 짧고 빠른 :
SELECT u.name , count(*) FILTER (WHERE g.winner_id > 0) AS played , count(*) FILTER (WHERE g.winner_id = u.id) AS won , count(*) FILTER (WHERE g.winner_id <> u.id) AS lost FROM games g JOIN users u ON u.id IN (g.player_1_id, g.player_2_id) GROUP BY u.name;
포스트 그레스 9.3 (또는 버전)이 중첩 된 서브 - 선택 또는 CASE 식 여전히보다 짧고 빠르다 :
SELECT u.name , count(g.winner_id > 0 OR NULL) AS played , count(g.winner_id = u.id OR NULL) AS won , count(g.winner_id <> u.id OR NULL) AS lost FROM games g JOIN users u ON u.id IN (g.player_1_id, g.player_2_id) GROUP BY u.name;
세부:
-
==============================
2.이 상관 관계 서브 쿼리는 논리를 단순화 할 수있는 경우이다 :
이 상관 관계 서브 쿼리는 논리를 단순화 할 수있는 경우이다 :
select u.*, (played - won) as lost from (select u.*, (select count(*) from games g where g.player_1_id = u.id or g.player_2_id = u.id ) as played, (select count(*) from games g where g.winner_id = u.id ) as won from users u ) u;
이것은 아무 관계가없는 것으로 간주합니다.
-
==============================
3.
select users.name, count(case when games.winner_id > 0 then games.name else null end) as played, count(case when games.winner_id = users.id then games.name else null end) as won, count(case when games.winner_id != users.id then games.name else null end) as lost from users inner join games on games.player_1_id = users.id or games.player_2_id = users.id group by users.name;
from https://stackoverflow.com/questions/27136251/aggregate-columns-with-additional-distinct-filters by cc-by-sa and MIT license
'SQL' 카테고리의 다른 글
[SQL] SELECT *에 대한 바로 가기가 FROM 있습니까? (0) | 2020.04.08 |
---|---|
[SQL] 쉼표로 구분 된 목록의 MySQL의 항목을 계산하는 방법 (0) | 2020.04.08 |
[SQL] 무엇을 의미 = *는 무엇입니까? (0) | 2020.04.08 |
[SQL] 와이즈 최대 (0) | 2020.04.08 |
[SQL] SELECT 쿼리의 기본 행 순서 - SQL 2012 대 SQL 서버 2008 (0) | 2020.04.08 |