我正在显示一棵类别树,并且在每个分支旁边,我希望统计相同级别或更低级别的列表数量。
所有列表的catid处于最低类别级别。也就是说,如果可用的类别级别较低,则不能将特定的catid应用于列表。
例如,在下面的“列表”表中,您找不到具有catid = 24的列表,因为这还不是该分支中树的最低级别。
在我的类别数据库中,最多有4个级别(0-3)。
以下是表格:
所有类别(表)
record_id parent_category_id parent_id title level
---------------------------------------------------------------------
24 NULL NULL Real Estate 0
5915 24 24 Residential 1
7569 5915 24 For sale 2
列表(表格)
record_id cat_id
--------------------
1 7569
2 8847
因此,我的HTML类别树应如下所示:
HTML
Categories Listing count
-------------------------------------
24 1
5915 1
7569 1
因此,在我的html和jQuery代码中,我将任意级别的特定catid传递给查询,并且该目录应查找该级别或更低级别的列表。
我已经尝试了几个小时,到目前为止我的努力还不值得一试。但是我还是会...
编辑:到目前为止,我的努力(别笑了,经过数小时的尝试,事情变得混乱了):
select l.record_id
from listings l
where catid in (
select record_id
from all_categories
where record_id = 5915)
or catid in (
select parent_category_id
from all_categories
where parent_category_id = 5915)
or catid in (
select parent_id
from all_categories
where parent_id = 5915)
答案 0 :(得分:1)
孩子的0级parent_id保留在“ all_categories”表中。
因此,一个孩子可以通过其共同的parent_id与其他孩子链接。
然后同时添加级别0。
困难在于给定的孩子ID不在“列表”表中。
因此,要检索该列表record_id,必须通过类别。
可以在here上找到关于妊娠酯的测试
SELECT
cat.record_id as catId,
pl.listId AS ListingCount,
cat.level
FROM
(
SELECT
cat1.parent_id,
MAX(list.record_id) AS listId
FROM all_categories AS cat1
JOIN all_categories AS cat2 ON cat2.parent_id = cat1.parent_id
JOIN listings list ON list.cat_id = cat2.record_id
WHERE cat1.record_id = 5915
GROUP BY cat1.parent_id
) AS pl
LEFT JOIN all_categories AS cat ON (cat.parent_id = pl.parent_id OR cat.record_id = pl.parent_id)
ORDER BY cat.record_id, cat.level;
结果:
catId ListingCount level
24 1 0
5915 1 1
7569 1 2
查询中还包括“级别”,因为它可用于生成HTML中的类别树。
请注意,如果“列表”表仅包含级别0的cat_id,则可以大大简化查询
答案 1 :(得分:1)
假设树的最大深度为四级,则可以使用多个LEFT JOIN检索完整的树或子树。但是,这不会是超级高效的。考虑以下查询:
SET @subtree_id = 1;
SELECT
c0.category_id AS c0_id, c0.name AS c0_name,
c1.category_id AS c1_id, c1.name AS c1_name,
c2.category_id AS c2_id, c2.name AS c2_name,
c3.category_id AS c3_id, c3.name AS c3_name,
l.listing_id
FROM category AS c0
LEFT JOIN category AS c1 ON c1.parent_id = c0.category_id
LEFT JOIN category AS c2 ON c2.parent_id = c1.category_id
LEFT JOIN category AS c3 ON c3.parent_id = c2.category_id
LEFT JOIN listing AS l ON l.category_id = c0.category_id
OR l.category_id = c1.category_id
OR l.category_id = c2.category_id
OR l.category_id = c3.category_id
WHERE c0.category_id = @subtree_id;
它将产生如下结果:
| c0_id | c0_name | c1_id | c1_name | c2_id | c2_name | c3_id | c3_name | listing_id |
|-------|-------------|-------|-------------|-------|-----------|-------|------------|------------|
| 1 | Real Estate | 2 | Residential | 3 | House | NULL | NULL | NULL |
| 1 | Real Estate | 2 | Residential | 4 | Apartment | NULL | NULL | 1 |
| 1 | Real Estate | 2 | Residential | 4 | Apartment | NULL | NULL | 2 |
| 1 | Real Estate | 2 | Residential | 4 | Apartment | NULL | NULL | 3 |
| 1 | Real Estate | 2 | Residential | 5 | Condo | NULL | NULL | NULL |
| 1 | Real Estate | 6 | Commercial | 7 | Office | NULL | NULL | 4 |
| 1 | Real Estate | 6 | Commercial | 8 | Retail | NULL | NULL | 5 |
| 1 | Real Estate | 6 | Commercial | 9 | Other | 10 | Industrial | 6 |
不幸的是,它仅包含完整路径。要达到预期的结果,只需将每行分成4行:
SET @subtree_id = 1;
SELECT
CASE WHEN level >= 0 THEN c0_id END AS c0_id, CASE WHEN level >= 0 THEN c0_name END AS c0_name,
CASE WHEN level >= 1 THEN c1_id END AS c1_id, CASE WHEN level >= 1 THEN c1_name END AS c1_name,
CASE WHEN level >= 2 THEN c2_id END AS c2_id, CASE WHEN level >= 2 THEN c2_name END AS c2_name,
CASE WHEN level >= 3 THEN c3_id END AS c3_id, CASE WHEN level >= 3 THEN c3_name END AS c3_name,
COUNT(listing_id) AS lc
FROM (
SELECT
c0.category_id AS c0_id, c0.name AS c0_name,
c1.category_id AS c1_id, c1.name AS c1_name,
c2.category_id AS c2_id, c2.name AS c2_name,
c3.category_id AS c3_id, c3.name AS c3_name,
l.listing_id
FROM category AS c0
LEFT JOIN category AS c1 ON c1.parent_id = c0.category_id
LEFT JOIN category AS c2 ON c2.parent_id = c1.category_id
LEFT JOIN category AS c3 ON c3.parent_id = c2.category_id
LEFT JOIN listing AS l ON l.category_id = c0.category_id
OR l.category_id = c1.category_id
OR l.category_id = c2.category_id
OR l.category_id = c3.category_id
WHERE c0.category_id = @subtree_id
) AS paths
INNER JOIN (
SELECT 0 AS level UNION ALL
SELECT 1 UNION ALL
SELECT 2 UNION ALL
SELECT 3
) AS levels ON level = 0 AND c0_id IS NOT NULL
OR level = 1 AND c1_id IS NOT NULL
OR level = 2 AND c2_id IS NOT NULL
OR level = 3 AND c3_id IS NOT NULL
GROUP BY 1, 2, 3, 4, 5, 6, 7, 8
ORDER BY 2, 1, 4, 3, 6, 5, 8, 7
答案 2 :(得分:1)
您有一个神秘的数据结构,但是问题似乎并不那么困难。这似乎可以满足您的要求:
select c2.record_id, count(*)
from listings l join
all_categories c
on l.cat_id = c.record_id join
all_categories c2
on c2.record_id in (c.record_id, c.parent_category_id, c.parent_id)
group by c2.record_id, l.cat_id
order by l.cat_id, c2.record_id;
这个想法很简单。表all_categories
具有完整的层次结构。基本上,您需要将层次结构的所有级别移动到单独的行中,以便可以对其进行汇总。
join
至c2
就是这样做的。剩下的只是聚合。
答案 3 :(得分:0)
在mysql 8中,有一个(with)函数可以递归运行,您可以获取catId的级别
结构->(id cat parent_id) ->(1,24,NULL),(2,5915,1),(3,7569,2),(4,3,1)
WITH recursive parent(id,parent_id,Levels) AS
(
select id,parent_id, 0 as Levels from table where id =1 //condition
union all
select c.id,c.parent_id,(Levels+1) as Levels from table as c inner join parent as p1 on p1.id = c.parent_id
)
SELECT *
FROM parent
唯一的限制是它在我的sql版本8.x中,其余代码可以正常运行,您可以问这种方法的任何问题称为cet希望对您有所帮助
答案 4 :(得分:0)
对于每个record_id,左键联接子代,然后计算每个级别的唯一值并将它们加在一起。
select n.record_id
count(distinct n.record_id)+count(distinct n2.record_id)+count(distinct
n3.record_id)+count(distinct n4.record_id) listingcount
from all_categories n
left join all_categories n2 on n.record_id=n2.parent_category_id
left join all_categories n3 on n2.record_id=n3.parent_category_id
left join all_categories n4 on n3.record_id=n4.parent_category_id
group by n.record_id
答案 5 :(得分:0)
我相信这适合于递归sql。
CREATE FUNCTION f_total_listings(@root_id INT) RETURNS INT AS
BEGIN
DECLARE @listing_count INT;
WITH cat (record_id, parent_category_id) AS
(
SELECT root.record_id, root.parent_category_id
FROM all_categories AS root
WHERE root.parent_category_id = @root_id
UNION ALL
SELECT child.record_id, child.parent_category_id
FROM cat AS parent, all_categories AS child
WHERE parent.record_id = child.parent_category_id
)
SELECT @listing_count = count(*)
FROM listings l
JOIN cat ON l.cat_id = cat.record_id;
RETURN @listing_count;
END;
SELECT record_id, f_total_listings(record_id) FROM all_categories