Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/56.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 在类别树中的某个位置选择具有类别id的记录_Mysql_Sql - Fatal编程技术网

Mysql 在类别树中的某个位置选择具有类别id的记录

Mysql 在类别树中的某个位置选择具有类别id的记录,mysql,sql,Mysql,Sql,我正在显示一个类别树,在每个分支旁边,我想要一个相同级别或更低级别的列表数 所有列表都具有最低类别级别的catid。i、 e.如果有较低的类别级别可用,则无法将特定catid应用于列表 例如,在下面的listings表中,您无法找到catid=24的列表,因为这还不是该分支树中的最低级别 在我的类别数据库中,最多有4个级别0-3 以下是表格: 所有类别表 列表表 因此,我的HTML类别树应该如下所示: HTML 因此,在我的html和jQuery代码中,我将任何级别的特定catid传递给查询,它

我正在显示一个类别树,在每个分支旁边,我想要一个相同级别或更低级别的列表数

所有列表都具有最低类别级别的catid。i、 e.如果有较低的类别级别可用,则无法将特定catid应用于列表

例如,在下面的listings表中,您无法找到catid=24的列表,因为这还不是该分支树中的最低级别

在我的类别数据库中,最多有4个级别0-3

以下是表格:

所有类别表

列表表

因此,我的HTML类别树应该如下所示:

HTML

因此,在我的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级父级\u id保留在“所有\u类别”表中

因此,一个孩子可以通过他们共同的父母id链接到其他孩子。 然后同时包含级别0

困难在于给定的子id不在列表表中。 因此,要检索列表记录的id,它必须通过类别

可以找到rextester上的测试

选择 类别记录id为catId, pl.listId作为ListingCount, 猫级 从…起 选择 cat1.1父项id, MAXlist.record_id作为listId 从所有类别中选择cat1 将所有类别连接为cat2上的cat2.parent\u id=cat1.parent\u id 在list.cat\u id=cat2.record\u id上加入列表列表 其中cat1.record_id=5915 按cat1.parent\u id分组 作为pl 以cat.parent\u id=pl.parent\u id或cat.record\u id=pl.parent\u id的形式左键连接所有类别 按类别记录的订单,类别级别; 结果:

catId   ListingCount    level
24      1               0
5915    1               1
7569    1               2
该级别也包含在查询中,因为它可以用于生成HTML中的类别树


请注意,如果listings表仅包含级别0的cat_id,则查询可以简化很多。假设树的最大深度为四级,则可以使用多个左连接来检索完整树或子树。但这并不是超高效的。考虑下面的查询:

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

在mysql 8中,有一个with函数递归运行,您可以获得catId的级别

结构->id类别父项\u id ->1,24,空,25915,1,37569,2,4,3,1


唯一的限制是,在我的sql 8.x版本中,代码可以正常运行。您可以询问的任何问题都可以使用此方法。此方法称为cet hope it help

对于每个记录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

你有一个神秘的数据结构,但问题似乎并不那么难。这似乎是你想要的:

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具有完整的层次结构。基本上,您需要将层次结构的所有级别移动到单独的行中,以便对它们进行聚合


这就是连接到c2的功能。其余的只是聚合。

我认为这适合于递归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

SQL问题通常需要仔细选择覆盖所有边缘情况的最小但完整的样本数据,以及相应的表格形式的预期输出。读一次:你有什么版本?使用MySQL 8.0的递归CTE,此任务可能会更容易。是否要显示没有列表的空类别?
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
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
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;
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