我有一个MySQL表,其格式如下:
CREATE TABLE IF NOT EXISTS `Company` (
`CompanyId` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
`Name` VARCHAR(45) NULL ,
`Address` VARCHAR(45) NULL ,
`ParentCompanyId` INT UNSIGNED NULL ,
PRIMARY KEY (`CompanyId`) ,
INDEX `fk_Company_Company_idx` (`ParentCompanyId` ASC) ,
CONSTRAINT `fk_Company_Company`
FOREIGN KEY (`ParentCompanyId` )
REFERENCES `Company` (`CompanyId` )
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
因此,为了澄清,我有可以拥有母公司的公司。这可能会导致以下示例表内容:
CompanyId Name Address ParentCompanyId
1 Foo Somestreet 3 NULL
2 Bar Somelane 4 1
3 McD Someway 1337 1
4 KFC Somewhere 12 2
5 Pub Someplace 2 4
现在我的问题出现了。 我想检索CompanyId 2递归的所有子项。因此,应显示以下结果集:
CompanyId Name Address ParentCompanyId
4 KFC Somewhere 12 2
5 Pub Someplace 2 4
我想过使用With ... AS ...
语句,但MySQL不支持它。我想到的另一个解决方案是使用一个返回结果集的过程或函数,并将其与该函数的递归调用结合起来。但MySQL只支持列类型作为返回值。
我想到的最后一个可能的解决方案是创建一个包含两个字段的表:CompanyId和HasChildId。然后我可以编写一个程序,通过公司递归循环,并通过companyid填充所有递归子表。在这种情况下,我可以编写一个连接此表的查询:
SELECT CompanyId, Name, Address
FROM Company C -- The child
INNER JOIN CompanyChildMappingTable M
ON M.CompanyId = C.HasChildId
INNER JOIN Company P -- The parent
ON P.CompanyId = M.CompanyId
WHERE P.CompanyId = 2;
如果我每隔24小时调用一次该程序,并且在将新记录插入Company
时动态填写表格,则此选项应该是快速的。但这可能非常棘手,我应该通过在公司表上编写触发器来实现这一点。
我想听听你的意见。
解决方案:我已经构建了以下过程来填充我的表(现在它只返回SELECT结果)。
DELIMITER $$
DROP PROCEDURE IF EXISTS CompanyFillWithSubCompaniesByCompanyId$$
CREATE PROCEDURE CompanyFillWithSubCompaniesByCompanyId(IN V_CompanyId BIGINT UNSIGNED, IN V_TableName VARCHAR(100))
BEGIN
DECLARE V_CONCAT_IDS VARCHAR(9999) DEFAULT '';
DECLARE V_CURRENT_CONCAT VARCHAR(9999) DEFAULT '';
SET V_CONCAT_IDS = (SELECT GROUP_CONCAT(CompanyId) FROM Company WHERE V_CompanyId IS NULL OR ParentCompanyId = V_CompanyId);
SET V_CURRENT_CONCAT = V_CONCAT_IDS;
IF V_CompanyId IS NOT NULL THEN
companyLoop: LOOP
IF V_CURRENT_CONCAT IS NULL THEN
LEAVE companyLoop;
END IF;
SET V_CURRENT_CONCAT = (SELECT GROUP_CONCAT(CompanyId) FROM Company WHERE FIND_IN_SET(ParentCompanyId, V_CURRENT_CONCAT));
SET V_CONCAT_IDS = CONCAT_WS(',', V_CONCAT_IDS, V_CURRENT_CONCAT);
END LOOP;
END IF;
SELECT * FROM Company WHERE FIND_IN_SET(CompanyId, V_CONCAT_IDS);
END$$
答案 0 :(得分:0)
参考:
<强> Recursive MySQL Query with relational innoDB 强>
和
<强> How to find all child rows in MySQL? 强>
它应该了解如何在MYSQL
答案 1 :(得分:0)
最快的搜索方式是,使用公司ID值为2. companyId = parentId * 2然后查询数据库,选择* from company where((CompanyId%$ parentId)== 0) 我尝试了这个代码,它很快但问题是它创建了child的id为parentId * 2,如果子深度变深,int,float可能会超出范围。所以,我重新创建了我的整个程序。