2013-03-17 4 views
6

Ich habe zwei Tabellen: Kategorien und Artikel. Ich habe Kategorien unter Verwendung der geschachtelten Satzstruktur gespeichert. Kategorien haben Gegenstände. Elemente können nur Blattknoten einer Stammkategorie hinzugefügt werden.Holen Sie sich die Anzahl der Elemente im Zusammenhang mit verschachtelten Kategorie in sql

Für zB: Kategorien

Vehicles 
    Bikes 
     Bajaj 
    Automobiles 
Art & Antiques 
    Amateur Art 

Items können in diesem Fall zur Kategorie Bajaj, Autos und Amateur Art hinzugefügt werden.

Lets sagen, es gibt zwei Elemente in Bajaj, 5 Elemente in PKWs, 2 Innen Amateur Art

Für Root-Ebene Kategorien I wie folgt angezeigt werden soll:

- Vehicles (7 items) 
- Art & Antiques (2 items) 

Wie kann ich das tun?

Hier ist der SQL-Dump mit einigen Beispieldaten

-- 
-- Table structure for table `categories` 
-- 

CREATE TABLE IF NOT EXISTS `categories` (
`id` int(11) NOT NULL AUTO_INCREMENT, 
`parent_id` int(11) DEFAULT NULL, 
`title` varchar(64) COLLATE utf8_unicode_ci NOT NULL, 
`lft` int(11) NOT NULL, 
`lvl` int(11) NOT NULL, 
`rgt` int(11) NOT NULL, 
`root` int(11) DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    KEY `IDX_3AF34668727ACA70` (`parent_id`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=28 ; 

-- 
-- Dumping data for table `categories` 
-- 

INSERT INTO `categories` (`id`, `parent_id`, `title`, `lft`, `lvl`, `rgt`, `root`) VALUES 
(22, NULL, 'Vehicles', 1, 0, 8, 22), 
(23, 22, 'Bikes', 2, 1, 5, 22), 
(24, 23, 'Bajaj', 3, 2, 4, 22), 
(25, 22, 'Automobiles', 6, 1, 7, 22), 
(26, NULL, 'Art & Antiques', 1, 0, 4, 26), 
(27, 26, 'Amateur Art', 2, 1, 3, 26); 

-- -------------------------------------------------------- 

-- 
-- Table structure for table `items` 
-- 

CREATE TABLE IF NOT EXISTS `items` (
`id` int(11) NOT NULL AUTO_INCREMENT, 
`category_id` int(11) NOT NULL, 
`title` varchar(100) NOT NULL, 
PRIMARY KEY (`id`), 
KEY `FK_403EA91BA33E2D84` (`category_id`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=5 ; 

-- 
-- Dumping data for table `items` 
-- 

INSERT INTO `items` (`id`, `category_id`, `title`) VALUES 
(1, 24, 'Pulsor 150 cc'), 
(2, 24, 'Discover 125 cc'), 
(3, 27, 'Art of dream'), 
(4, 25, 'Toyota Car'); 

-- 
-- Constraints for dumped tables 
-- 

-- 
-- Constraints for table `categories` 
-- 
ALTER TABLE `categories` 
ADD CONSTRAINT `FK_3AF34668727ACA70` FOREIGN KEY (`parent_id`) REFERENCES `categories` (`id`) ON DELETE SET NULL; 

-- 
-- Constraints for table `items` 
-- 
ALTER TABLE `items` 
ADD CONSTRAINT `FK_403EA91BA33E2D84` FOREIGN KEY (`category_id`) REFERENCES `categories` (`id`) ON DELETE CASCADE; 

Wurzelknoten haben NULL im Bereich der parent_id

-Update zu arbeiten:

ich für Wurzeln mit diesem holen konnte Abfrage:

SELECT c.id,c.title,cte.co FROM categories c 
JOIN 
(SELECT 
    c0_.id,c0_.root,COUNT(i.id) co 
    FROM 
    categories c0_ 
    JOIN items i ON c0_.id=i.category_id 
    WHERE c0_.rgt = 1 + c0_.lft 
    GROUP BY c0_.id 
) cte 
ON cte.root=c.id 
WHERE c.parent_id is null 

Die obige Abfrage funktioniert für Root-Kategorie. Wenn der Benutzer jetzt auf die Stammebene klickt, möchte ich dasselbe tun.

für zB wenn jemand auf Fahrzeuge klickt sollte ich:

Bikes (2) 
Automobiles (5) 

Dafür habe ich versucht:

SELECT c.id,c.title,cte.co FROM categories c 
JOIN 
(SELECT 
    c0_.id,c0_.root,COUNT(i.id) co 
    FROM 
    categories c0_ 
    JOIN items i ON c0_.id=i.category_id 
    WHERE 
    c0_.rgt = 1 + c0_.lft 
    GROUP BY c0_.id 
) cte 
ON cte.root=c.id 
WHERE c.parent_id=1 

Dieses leere Ergebnismenge zurück. Was ist falsch in dieser Abfrage?

+1

funktioniert die verschachtelten Satz Teil dieses Artikels http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/ – Sebas

Antwort

2
SELECT parent.title, 
(SELECT count(i.id) count FROM items i 
WHERE category_id IN 
(
SELECT child.id FROM categories child WHERE child.lft>=parent.lft AND 
    child.rgt<=parent.rgt AND child.root=parent.root 
) 
) 
FROM categories parent 
WHERE [email protected]_id; 

Bitte informieren Sie mich, wenn dies nicht

0

So etwas sollte funktionieren.

select c1.title, count(*) itemcount 
from categories c1 join categories c2 
on c2.parent_id = c1.id 
join items on items.category_id = c2.id 
group by c1.title 
+0

dies nur für die se aufstehen Cond-Ebene. – Ambrose

+0

Diese Abfrage gibt auch die Fahrradkategorie zurück, die sich innerhalb der Fahrzeugkategorie befindet. – sonam

1

Wie wäre es etwa so:

SELECT COUNT(items.id), 
    (SELECT lookup.title 
    FROM categories lookup 
    WHERE lookup.id = categories.root) 
FROM items, categories 
WHERE categories.id = items.category_id 
GROUP BY categories.root; 

auf der Grundlage der Eingabe von dem Skript oben gibt mir:

3 | Vehicles 
1 | Art & Antiques 

für eine bestimmte Wurzel zu wählen hinzufügen

AND categories.root = @id 

wo @id ist Ihre Root-ID yo suchst du?

Alternativ, wenn Sie mit dem Grundton auswählen möchten etwas tun (unheimlich) wie folgt aus:

SELECT title, total 
    FROM 
    (SELECT COUNT(items.id) total, 
      (SELECT lookup.title 
     FROM categories lookup 
     WHERE lookup.id = categories.root) title 
    FROM items, categories 
    WHERE categories.id = items.category_id 
    GROUP BY categories.root; 
    ) AS some_table 
WHERE some_table.title = @root_name 

wo @root_name ist der Name des Root-Knotens (in Anführungszeichen natürlich)

+0

Ja, es gibt das korrekte Ergebnis für oben. Wie bekomme ich einen bestimmten Wurzelknoten zB nur für Fahrzeuge? – sonam

+0

Wenn Sie die Root-Knoten-ID wissen, fügen Sie einfach "WHERE categories.root = " zur äußeren Auswahl hinzu (vor der Gruppe durch)? Es sei denn, Sie möchten nach Titel auswählen? –

+0

Bearbeitete meine Antwort für beide Optionen –

Verwandte Themen