1つのMySQLのクエリで複数の項目のカウントは誤った結果を返します。

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');

ここでは、画像の説明を入力します。

その後、私はこのクエリを実行すると、他のものの数の中で、そのpmtsdownloadsおよび特別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

SQLFiddleのデモ

おすすめ

転載: http://10.200.1.11:23101/article/api/json?id=395821&siteId=1