5

カテゴリとアイテムの2つのテーブルがあります。ネストされたセット構造を使用してカテゴリを保存しました。カテゴリにはアイテムがあります。アイテムは、ルートカテゴリのリーフノードにのみ追加できます。

例:カテゴリ

Vehicles
    Bikes
        Bajaj
    Automobiles
Art & Antiques
    Amateur Art

この場合、アイテムはカテゴリBajaj、Automobiles、AmateurArtに追加できます。

Bajaj内に2つのアイテム、Automobiles内に5つのアイテム、AmateurArt内に2つのアイテムがあるとします。

ルートレベルのカテゴリについては、次のように表示します。

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

これどうやってするの ?

これがいくつかのサンプルデータで動作するSQLダンプです

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

ルートノードのparent_idのフィールドにNULLがあります

アップデート:

このクエリを使用してルートをフェッチすることができました:

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

上記のクエリは、ルートレベルのカテゴリで機能します。これで、ユーザーがルートレベルのカテゴリをクリックしたときに、同じことを実行したいと思います。

たとえば、誰かが車をクリックしたとき、私は次のことを取得する必要があります。

 Bikes (2)
 Automobiles (5)

そのために私は試しました:

 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

これにより、空の結果セットが返されました。このクエリの何が問題になっていますか?

4

3 に答える 3

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 parent.parent_id=@parent_id;

これが機能しない場合はお知らせください

于 2013-03-18T06:26:16.193 に答える
1

このようなものはどうですか:

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;

上記のスクリプトからの入力に基づいて、次のようになります。

3 | Vehicles
1 | Art & Antiques

特定のルートを選択するには追加

AND categories.root = @id

ここで、@idは探しているルートIDです。

または、ルート名で選択する場合は、次のような(怖い)ことを行います。

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

ここで、@ root_nameはルートノードの名前です(もちろん引用符で囲みます)

于 2013-03-17T04:52:51.050 に答える
0

このようなものが機能するはずです。

 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
于 2013-03-17T03:05:40.173 に答える