通过一个查询接收产品组和产品

时间:2011-01-11 10:34:47

标签: sql sqlite

我有两张桌子:

Product
------------------------------------
id   group_id   name   quick_select
------------------------------------
1      1       product1      1
2      3       product2      0
3      5       product3      1

Product_group
-----------------------
id   name   parent_id
-----------------------
1   group1     0
2   group2     0
3   group3     1
4   group4     1
5   group5     3

我为快速选择产品制作导航系统。我向用户显示类别,用户可以通过单击“类别”按钮在其中导航,然后逐级降级到子类别并下降到很多级别,最后它不能更深入 - 然后我展示产品。首先,我展示其下有产品的根类别,以及这些根类别子类别,子类别等。

在我的查询中,我想要选择所有根类别(其中parent_id = 0),如果有产品及其子类别和子子类别等,其中quick_select必须在产品表中为1。而且我不知道类别的深度 - 有多少级别。

一个查询可以吗?或者我需要做两个查询吗?

到目前为止,我用这个查询做了:

SELECT pg.id, pg.name, pg.parent_id AS parent_id
FROM product_group AS pg
LEFT JOIN product AS p ON pg.id = p.group_id
WHERE pg.parent_id = 0 AND p.id IS NOT NULL AND p.quick_select = 1
GROUP BY pg.id

但是我没有收到子类别为空的根类别,哪个子类别为空,在此下面是另一个子类别,其中包含quick_select = 1的产品。

抱歉我的英语不好。

我想收到所有类别,其中quick_select = 1的产品不是产品

-- Category
|     |
|   product
|
-- Category
      |
   Category
      |
   Category
      |
 multiple products 

1 个答案:

答案 0 :(得分:1)

坏消息是你不能在SQLite中这样做,至少在这个数据结构中,因为SQLite不支持递归SQL或窗口函数。

如果选择性能很重要,您可以尝试组织这样的数据: http://articles.sitepoint.com/article/hierarchical-data-database/2

另一种选择是在输入时将root id添加到每一行。

基本上,在某些时候,您将不得不使用多个选择并确定应用程序级别的根ID。

<强>更新 好吧,这是非常伪代码,但它应该让你到那里。

您需要一种具有某种hashmap或命名数组数据类型的语言。

hashmap results, parent, nodes, nodes_new; # variables


foreach  (res in sql_execute("SELECT id, parent_id FROM product_group;") ) {
    parent[res.id] = res.parent_id;
}

# get groups with products
foreach  (res in sql_execute("SELECT pg.id FROM product_group AS pg INNER JOIN 
        product AS p ON pg.id = p.group_id 
        WHERE p.quick_select = 1 GROUP BY pg.id ") ) {
    nodes[res.id] = res.id;
}

while (length(nodes) > 0) {
    foreach (i in nodes) {
        if (i = 0) { results[i] = i; } # if its a root node, add to results
        else { nodes_new[parent[i]] = parent[i]; } # otherwise, add parent to the next round
    }
    nodes = nodes_new; # prepare for next round
}

print results;