2009-04-02 2 views
2

나는이 문제를 쉽게 생각할 수 있지만 여러 번이 문제를 겪었으며 검색 (어쩌면 내가 무엇을 검색해야할지 모르겠다)이나 평가판을 통해 해결책을 찾을 수 없다. 오류. 당신이 볼 수 있듯이1 쿼리에서 1 : n 관계로 두 테이블의 모든 레코드를 계산하려면 어떻게합니까?

CREATE TABLE `table_a` (
    `id` int(11) NOT NULL auto_increment, 
    `table_b_id` int(11) NOT NULL, 
    `field` varchar(10) NOT NULL, 
    PRIMARY KEY (`id`), 
    KEY `table_b_id` (`table_b_id`) 
); 

INSERT INTO `table_a` VALUES(1, 1, 'test 1'); 
INSERT INTO `table_a` VALUES(2, 1, 'test 2'); 
INSERT INTO `table_a` VALUES(3, 0, 'test 3'); 

CREATE TABLE `table_b` (
    `id` int(11) NOT NULL auto_increment, 
    `name` varchar(10) NOT NULL, 
    PRIMARY KEY (`id`) 
); 

INSERT INTO `table_b` VALUES(1, 'value 1'); 
INSERT INTO `table_b` VALUES(2, 'value 2'); 

table_b의 ID 2 table_a에서 사용되지 않으며 table_a에 ID 3 table_b_id 0의 값을 가진다 :

나는 다음과 같은 테이블 구조와 데이터를 가지고있다. 내가하고 싶은 일은 012의 각 값이 table_a에 사용 된 횟수를 검색하는 것입니다. 2는 table_b이고, 모든 값의 수는 table_b이 아닙니다.

것은 내가 다음 쿼리와 함께 올라와있다 :

SELECT b.name, COUNT(a.id) AS number 
FROM table_a AS a 
LEFT JOIN table_b AS b ON (b.id = a.table_b_id) 
GROUP BY a.table_b_id 

그러나 그것은 분명히에만 다음 반환

name  number 
----------------- 
null  1 
value 1 2 
value 2 0 
:

name  number 
----------------- 
null  1 
value 1 2 

을 난 단지 SQL과 다음을 얻을 수있는 방법

MySQL을 사용하고 있습니다. 대답은 간단하다고 생각합니다.

편집 : union'd 쿼리 이외에 다른 방법이 있습니까?

답변

1
SELECT b.name, SUM(case when a.id is null then 0 else 1 end) AS number 
FROM table_a AS a 
RIGHT JOIN table_b AS b ON (b.id = a.table_b_id) 
GROUP BY b.id 

null 행을 가져 오려면이 것이 좋습니다. 나는 당신이 그것을 연합해야한다고 믿습니다.

SELECT b.name, SUM(case when a.id is null then 0 else 1 end) AS number 
FROM table_a AS a 
RIGHT JOIN table_b AS b ON (b.id = a.table_b_id) 
GROUP BY b.id 
UNION 
select null, count(1) from table_a where table_b_id not in (select id from table_b) 
+0

table_b (a.id = 3)에없는 것을 제외합니다. –

+0

어, 당신은 그냥 왼쪽 조인에서 nulls의 개수와 함께 그것을 조합 수 있지만, 제이미의 작품을 훔치지 않을 것입니다. 처음 질문을 올렸을 때 그 질문에 답을 할 수 있었지만 그때는 삭제 됐고, 나는 잊어 버렸습니다! – AaronLS

+0

죄송합니다. 약간 다른 질문입니다. 나는 테이블 b뿐만 아니라 두 테이블 모두에 모든 레코드가 필요하다는 것을 잊었다. 기본적으로 모든 사람들에게 그들이 틀렸다고 말하는 것으로 바꾸고 싶지 않았습니다. –

0

이 중첩 된 쿼리는 FULL OUTER JOIN라고 당신이 여기에서하고 싶은 MySQL의 5

SELECT b.name, (SELECT COUNT(*) FROM table_a AS a WHERE a.table_b_id = b.id) AS amount FROM table_b AS b 
+0

이것은 table_b에없는 것을 제외합니다 (a.id = 3). –

1

와 함께 작동합니다.

현재로서는 MySQL에는이 기능이 없습니다. 즉, 에뮬레이트해야하는 것은 UNION입니다 (단 하나의 쿼리에서 여전히 그렇듯이 그렇게 나쁘지 않습니다).

SELECT name, SUM(IF(a.id IS NULL, 0, 1)) 
FROM table_b b 
LEFT JOIN 
     table_a a 
ON  a.table_b_id = b.id 
GROUP BY 
     b.id 
UNION ALL 
SELECT name, COUNT(*) 
FROM table_a a 
LEFT JOIN 
     table_b b 
ON  b.id = a.table_b_id 
WHERE b.id IS NULL 
GROUP BY 
     b.id 
0

this post by Xaprb에서이 문제를 해결하기위한 다양한 방법에 대한 토론이 있습니다. 그는 UNION을 사용하는 것을 피하는 방법을 보여줍니다. 대체 메커니즘에는 여분의 "뮤텍스"테이블이 필요하지만 그는 UNION을 사용하는 것보다 느립니다.