2

私はこのdbテーブルを持っています

CREATE TABLE IF NOT EXISTS `category` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `parent_id` int(11) NOT NULL,
  `name` varchar(100) NOT NULL,
  `inherit` enum('Y','N') NOT NULL DEFAULT 'N',
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=15 ;

--
-- Dumping data for table `category`
--

INSERT INTO `category` (`id`, `parent_id`, `name`, `inherit`) VALUES
(1, 0, 'Fruits', 'N'),
(2, 0, 'Electronics', 'N'),
(3, 0, 'Furniture', 'N'),
(4, 0, 'Garden', 'N'),
(5, 1, 'Apples', 'N'),
(6, 1, 'Bananas', 'N'),
(7, 5, 'Green Apples', 'Y'),
(8, 5, 'Red Apples', 'N'),
(9, 2, 'Mobiles', 'Y'),
(10, 2, 'Televisions', 'N'),
(11, 9, 'Android', 'N'),
(12, 9, 'iPhone', 'Y'),
(13, 7, 'One Dozen Green Apples', 'Y'),
(14, 7, 'Two Dozens Green Apples', 'N');

user_id、category_id を保持する別のテーブルがあります。たとえば、user_id 1000 は 1 と 5 を表示できます。この情報をセッションに入れて、クエリが次のようになるようにします。

SELECT *
FROM `category`
WHERE id
IN ( 1, 5 )

このクエリは示していますFruits > Apples-これはすべて正常に機能します。しかし、ユーザー 1000 には " " も表示されますが、 " " は表示Green Applesされないため、" "にマークを付けました。緑色のリンゴの下に継承 = 'Y' とマークされたサブカテゴリがある場合...たとえば、「1 ダースの緑色のリンゴ」もリストする必要があります!!Inherit = 'Yes'Green ApplesRed Apples

UNION を試してみようと思ったのですが、2 レベル以上深くする方法がわかりません...

SELECT * FROM (
    SELECT *
    FROM `category`
    WHERE id
    IN ( 1, 5 )

    UNION

    SELECT c.*
    FROM `category` c
    INNER JOIN `category` parent ON parent.id = c.id AND c.inherit = 'Y'
    WHERE c.parent_id
    IN ( 1, 5 )
) all_cats

あなたは私に何を提案しますか? クエリが簡単になる場合は、テーブル構造の変更を開いていますか? ありがとう

4

3 に答える 3

4

自己結合を試してください:

編集: WHERE句を入れるのを忘れました

SELECT
    a.name,
    b.name,
    c.name
FROM 
    category as a
LEFT JOIN category as b
    ON b.parent_id = a.id
INNER JOIN category as c
    ON c.parent_id = b.id
    AND c.inherit = 'Y'
WHERE
    a.id = 1

しかし、理想的な解決策は、これを行う再帰関数を持つことです。そのテーブルでは、カテゴリのツリーを記述しているためです。上記のクエリは静的であり、2 レベル (2 つのサブカテゴリ) に戻ります。私が理解していることから、動的なものが必要です。

以下の関数のようなもの:

public String getCategory(int categId){

    String sSql = "SELECT name FROM category WHERE id = " + categId ;
    String name = oDb.exec(sql).get("name");

    sSql = "SELECT id FROM category WHERE inherit = 'Y' AND parent_id = " + categId ;
    int nextCategId = oDb.exec(sql).get("id");

    if(nextCategId != null){
        return name + "," + getCategory(nextCategId);
    }else{
        return name;
    }

}

したがって、Apples カテゴリが継承されていると仮定すると、結果は次のgetCategory(1)ようになります。Fruits,Apples,Green Apples

于 2013-04-22T12:04:13.020 に答える
1

mysql で 1 つのクエリですべてのカテゴリを取得するには、カテゴリ ツリーの深さのレベルと同じ数の自己結合が必要になります。深度レベルが制限されていない場合、これは明らかに不可能です。ただし、ストアド プロシージャを使用して id を実行できます。

次のようなユーザーのカテゴリを含むテーブルがあるとします。

CREATE TABLE IF NOT EXISTS `user_category` (
  `user_id` int(11) NOT NULL,
  `category_id` int(11) NOT NULL,
  PRIMARY KEY (`user_id`,`category_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1;

次のようなデータを使用します。

INSERT INTO `user_category` ( `user_id`, `category_id` ) VALUES
( 1000, 1 ),
( 1000, 5 );

カテゴリの ID を格納する一時テーブルを作成し、cat_treeそれを user_category テーブルの特定の user_id のすべての親カテゴリで初期化し、最後の結合がまだ存在しないカテゴリを少なくとも 1 つ挿入している限り、ツリーの下に自己結合を繰り返すことができます。 .

DELIMITER //
DROP PROCEDURE IF EXISTS show_user_categories//
CREATE PROCEDURE show_user_categories( uid INT(11) )
BEGIN
  DECLARE found INT(11) DEFAULT 1;
  DROP TABLE IF EXISTS cat_tree;
  CREATE TABLE cat_tree (cat_id int(11) PRIMARY KEY) ENGINE=HEAP;
  INSERT INTO cat_tree
    SELECT category_id FROM user_category
    WHERE user_id = uid;
  SET found = ROW_COUNT();
  WHILE found > 0 DO
    INSERT IGNORE INTO cat_tree
      SELECT c_child.id FROM cat_tree c JOIN category c_child 
      WHERE c.cat_id = c_child.parent_id AND c_child.inherit = 'Y';
    SET found = ROW_COUNT();
  END WHILE;
  SELECT cat_id FROM cat_tree;
  DROP TABLE cat_tree;
END;//
DELIMITER ;

この手順により、特定の user_id のカテゴリ ID の完全なリストが得られます。

CALL show_user_categories( 1000 ); 

sqlfiddleで実際の例を参照してください。

于 2013-04-23T06:47:54.927 に答える
0

SQL Server の場合:

;with CTE as
(
select id,name from category where id in(1,5)
union all
select c.id,c.name from category c join CTE ct on  c.parent_id=ct.id and c.inherit='Y'
)


select * from CTE
于 2013-04-22T12:08:41.797 に答える