C00000FD :
말, 나는 같은 내 테이블을 정의하는 경우 :
create table `usrs` (
`id` INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
`fnm` TINYTEXT,
`lnm` TINYTEXT
);
insert into `usrs` (`fnm`, `lnm`)
VALUES
('John', 'Doe'), -- 1
('Mary', 'Smith'), -- 2
('Peter', 'Pan'), -- 3
('Michael', 'Jackson'); -- 4
create table `pmts` (
`id` INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
`uid` INT UNSIGNED, -- id in `usrs` table
`amt` DOUBLE,
`flgs` INT UNSIGNED
);
insert into `pmts` (`uid`, `amt`, `flgs`)
VALUES
('3', '0.99', 0),
('1', '1.50', 0x80),
('3', '2', 0x80),
('3', '0.99', 0),
('4', '1.30', 0),
('3', '2.40', 0),
('1', '2.55', 0x80);
create table `downloads` (
`id` INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
`uid` INT UNSIGNED, -- id in `usrs` table
`app` TINYTEXT
);
insert into `downloads` (`uid`, `app`)
VALUES
('2', 'Candy Crush'),
('2', 'Skype'),
('3', 'Word'),
('2', 'Calc'),
('4', 'Doom'),
('3', 'Notepad');
그럼 난이 쿼리, 다른 것들 카운트 중에서 실행할 때 pmts
, downloads
특수 flgs
각을 usr
:
-- this query contains additional clauses that were used in my production query
SELECT t1.*,
COUNT(t2.`id`) as cPmts, -- count `pmts` for each user
SUM(IF((t2.`flgs`&0x80)<>0, 1, 0)) as cPmtFlgs, -- count `pmts` with `flgs` equal to 0x80 for each user
COUNT(t3.`id`) as cDwds -- count `downloads` for each user
FROM `usrs` t1
LEFT JOIN `pmts` t2 ON t1.`id`=t2.`uid`
LEFT JOIN `downloads` t3 ON t1.`id`=t3.`uid`
WHERE t1.`id` > 0 -- just to simulate some condition
GROUP BY t1.`id`
ORDER BY t1.`fnm`, t1.`lnm` ASC
LIMIT 0, 10
빨간색으로 표시된 내가받은 결과, 잘못된 :
왜?
아이디 :
귀하의 문제가 있기 때문이다 Peter Pan
다수의 지불이 와 여러 다운로드, 그의 행이 중복되고있다 JOIN
(당신이를 제거하면 당신이 볼 수있는 GROUP BY
간단한와 쿼리에서 집계 함수를 대체 SELECT *
[데모]를 ). 이 문제를 해결하는 방법은 파생 테이블에서 집계하고 수행하는 것 JOIN
대신에 그 결과를 :
SELECT t1.*,
COALESCE(t2.cPmts, 0) AS cPmts, -- count `pmts` for each user
COALESCE(t2.cPmtFlgs, 0) AS cPmtFlgs, -- count `pmts` with `flgs` equal to 0x80 for each user
COALESCE(t3.cDwds, 0) AS cDwds -- count `downloads` for each user
FROM `usrs` t1
LEFT JOIN (SELECT uid,
COUNT(*) AS cPmts,
SUM(IF((`flgs`&0x80)<>0, 1, 0)) AS CpmtFlgs
FROM `pmts`
GROUP BY uid) t2 ON t1.`id`=t2.`uid`
LEFT JOIN (SELECT uid, COUNT(*) AS cDwds
FROM `downloads`
GROUP BY uid) t3 ON t1.`id`=t3.`uid`
WHERE t1.`id` > 0 -- just to simulate some condition
ORDER BY t1.`fnm`, t1.`lnm` ASC
LIMIT 0, 10
산출:
id fnm lnm cPmts cPmtFlgs cDwds
1 John Doe 2 2 0
2 Mary Smith 0 0 3
4 Michael Jackson 1 0 1
3 Peter Pan 4 1 2