Comment puis-je faire en sorte que ce SQL Fiddle obtienne des résultats à partir du sous-ensemble d'éléments renvoyés par GROUP BY ?

Tableau

CREATE TABLE IF NOT EXISTS `accounts` (
  `master_id` int(3) unsigned NOT NULL,
  `child_id` int(3) unsigned NOT NULL,
  `name` varchar(200) NOT NULL
);

Données

INSERT INTO `accounts` (`master_id`, `child_id`, `name`) VALUES
  ('222', '555', 'child_555'),
  ('111', '111', 'master_111'),
  ('111', '999', 'child_999'),
  ('111', '888', 'child_888'),
  ('222', '222', 'master_222'),
  ('222', '777', 'child_777'),
  ('111', '666', 'child_666');

Requête actuelle

SELECT 
master_id, 
name, 
count(*) as "Total Accounts"
FROM `accounts`
GROUP BY master_id ASC;

Résultats

+-----------+------------+-------+
| master_id |    name    | Total |
+-----------+------------+-------+
|       111 | master_111 |     4 |
|       222 | child_555  |     3 |
+-----------+------------+-------+

Attendu

 - Don't count child if child_id == master_id
 - Get correct name

+-----------+------------+-------+
| master_id |    name    | Total |
+-----------+------------+-------+
|       111 | master_111 |     3 |
|       222 | master_222 |     2 |
+-----------+------------+-------+
2
numediaweb 23 mai 2018 à 12:29

6 réponses

Meilleure réponse

Je pense qu'une simple agrégation avec une logique conditionnelle est la meilleure approche:

SELECT master_id,
       MAX(CASE WHEN child_id = master_id THEN name END) as name,
       SUM(child_id <> master_id) as "Total Accounts"
FROM `accounts`
GROUP BY master_id ASC;

Voici le SQL Fiddle pour cela.

3
Gordon Linoff 23 mai 2018 à 10:47

Utilisez l'expression case pour effectuer une agrégation conditionnelle :

select b.master_id, a.name, 
       sum(case when b.master_id <> b.child_id then 1 else 0 end) as "Total Accounts"
from `accounts` a
inner join `accounts` b on a.child_id = b.master_id
group by b.master_id 
order by b.master_id ASC; 

Cependant, la clause WHERE devrait également faire le travail.

select master_id, name, 
       count(*) as "Total Accounts"
from `accounts`
where master_id != child_id
group by master_id 
order by master_id ASC; 
1
Yogesh Sharma 23 mai 2018 à 09:45

Voici une solution sans auto-adhésion

SELECT 
  `master_id`, 
  max(case when `master_id` = `child_id` then `name` end) n,
  count(case when `master_id` != `child_id` then 1 end) as "Total Accounts"
FROM `accounts` a1
GROUP BY master_id ASC;

DEMO

0
Radim Bača 23 mai 2018 à 09:46
SELECT 
b.master_id, 
a.name,
count(*) as "Total Accounts"
FROM accounts b, accounts a
where b.master_id<>b.child_id
and a.child_id = b.master_id
GROUP BY b.master_id ASC;

Ou comme l'a suggéré M Khalid Junaid:

SELECT 
  b.master_id,
  a.name,
  COUNT(*) AS "Total Accounts" 
FROM
  accounts b 
  JOIN accounts a 
    ON b.master_id <> b.child_id 
    AND a.child_id = b.master_id 
GROUP BY b.master_id ASC 

Résultat:

master_id   name        Total Accounts
111         master_111  3
222         master_222  2
2
Mark 23 mai 2018 à 11:16

Essaye ça...

SELECT master_id, name, count(*) as "Total Accounts" 
FROM accounts where master_id != child_id
GROUP BY master_id ASC;
0
Hassan Farooq 23 mai 2018 à 09:40
select master_id, name, 
       sum(master_id != child_id) as Total
from `accounts`
group by master_id 
order by master_id ASC; 

Démo sur SQL Fiddle

0
cdaiga 23 mai 2018 à 09:37