2008-10-15 12 views
3

Cela peut être un peu difficile à expliquer, mais je vais essayer.Comment est-ce que j'écrirais cette requête mysql profonde à 3 niveaux?

Je souhaite afficher une liste de catégories (stockées dans 1 table) et le nombre de domaines associés à chaque catégorie (stockés dans une autre table).

La clé singe dans ce cas est que chaque domaine a un ensemble d'enregistrements qui lui sont associés (qui sont stockés dans une 3ème table). Je veux seulement montrer les catégories qui ont des domaines qui leur sont associés, et le nombre de domaines ne devrait refléter que les domaines qui ont des enregistrements qui leur sont associés (à partir de la 3ème table).

Ma requête en cours

SELECT r.rev_id, c.cat_id, c.cat_name, count(d.dom_id) As rev_id_count FROM reviews r 
INNER JOIN domains d ON r.rev_domain_from=d.dom_id 
INNER JOIN categories c ON d.dom_catid=c.cat_id 
WHERE rev_status = 1 
GROUP BY cat_name 
ORDER BY cat_name 

Ceci permet de sélectionner les noms des catégories correctes, mais montre un nombre de faux (de rev_id_count). Si la catégorie a 2 domaines, et que chaque domaine a 2 enregistrements, il affichera le nombre de 4, alors qu'il devrait être 2.

Répondre

3

Testé avec la configuration suivante:


CREATE TABLE Categories (Name nvarchar(50), ID int NOT NULL IDENTITY(1,1)) 
CREATE TABLE Domains (Name nvarchar(50), ID int NOT NULL IDENTITY(1,1), CID int) 
CREATE TABLE Records (Name nvarchar(50), ID int NOT NULL IDENTITY(1,1), DID int) 

INSERT INTO Records (DID) VALUES (1) 
INSERT INTO Records (DID) VALUES (1) 
INSERT INTO Records (DID) VALUES (2) 
INSERT INTO Records (DID) VALUES (2) 
INSERT INTO Records (DID) VALUES (3) 
INSERT INTO Records (DID) VALUES (3) 

INSERT INTO Domains (Name,CID) VALUES ('D1',1) 
INSERT INTO Domains (Name,CID) VALUES ('D2',1) 
INSERT INTO Domains (Name,CID) VALUES ('D5',1) 
INSERT INTO Domains (Name,CID) VALUES ('D3',2) 
INSERT INTO Domains (Name,CID) VALUES ('D4',2) 

INSERT INTO Categories (Name) VALUES ('1') 
INSERT INTO Categories (Name) VALUES ('2') 
INSERT INTO Categories (Name) VALUES ('3') 
+0

Le 'distinct' est la clé. –

0

Quelque chose comme ça?

SELECT c.name, count(d.id) 
FROM categories c 
JOIN domains d ON c.id = d.cid 
JOIN records r ON r.did = d.id 
GROUP BY c.name; 
+0

Thats ce que j'ai en ce moment. Il n'affiche pas les comptes corrects pour les domaines. si j'ai 2 domaines dans une catégorie, et chaque domaine a 2 enregistrements, il montrera le compte comme 4, au lieu de 2. –

+0

Est-ce que MySQL prend en charge COUNT (DISTINCT)? Ensuite, essayez COUNT (DISTINCT (d.id)). – Tomalak

+0

Merci Tamalak! Ça a marché! –

0

Commencez par sélectionner le domaine qui contient des enregistrements, puis renseignez les catégories correspondant au domaine.

donc quelque chose comme

SELECT * FROM records 
    INNER JOIN domains on <clause> 
    INNER JOIN categories on <clause> 
WHERE <something> 

Je ne peux pas expliquer cela aussi bien, mais trop souvent lors de l'écriture SQL il est facile de regarder les choses de la liste des champs que nous voulons dans la sélection et ont tendance à utilisez cela pour dicter la façon dont nous utilisons les tables pour construire les données. En fait, nous devrions nous pencher davantage sur la façon dont les données sont liées à la requête que nous sommes en train de construire (ce qui semble souvent revenir à l'avant).

+0

Aucun effet. Même résultat que ci-dessus. –

0

Extension sur la solution de AquilaX, il vous suffit de sélectionner le nom du domaine:

SELECT c.name, d.name, count(d.id) 
    FROM categories c 
    JOIN domains d ON c.id = d.cid 
    JOIN records r ON r.did = d.id 
GROUP BY c.name, d.name; 

qui devrait montrer:

Cat 1, Domain 1, 2 
Cat 1, Domain 2, 1 
Cat 2, Domain 3, 5 

etc ...

(non testé cependant)

2
select c.name, count(distinct d.did) from domains d 
    left join categories c on c.cid = d.cid 
    left join records r on r.did = d.did 
    group by c.name 

testé avec 2 catégories, 2 domaines par catégories, nombre aléatoire d'enregistrements par domaine. jeu de résultats:

name  count 
----  -----  
test  2 
test2 2 
Questions connexes