我有一个MySQL表,它包含一个varchar(191)列,用于定义文件夹的绝对路径。生成此表并使用外部进程与IMAP系统同步。没有"父母"任何类型的引用来确定文件夹层次结构。我会喜欢添加某种父引用(路径枚举,物化路径,嵌套集等),但这样做需要对同步系统进行一些重大修改,我宁愿避免做类似的事情。
此表的一个示例如下:
id name
1 INBOX
2 Sent Items
3 FolderOne
4 FolderOne/FolderOneOne
5 FolderOne/FolderOneOne/FolderOneOneOne
6 FolderOne/FolderOneOne/FolderOneOneTwo
7 FolderOne/FolderOneTwo
8 FolderOne/FolderOneTwo/FolderOneTwoOne
9 FolderOne/FolderOneTwo/FolderOneTwoTwo
10 FolderTwo
此表格可包含一个IMAP帐户的20,000个文件夹。
我真的想找到一种方法来选择层次结构中的某个级别,抓住这些文件夹然后找出这些文件夹中是否有任何子文件夹。
根文件夹是一个相当简单的查询(只给我不包含任何/
个字符的记录)。
说我想在根文件夹FolderOne
下找到下一级文件夹:
SELECT *
FROM folder
WHERE `name` LIKE 'FolderOne/%'
AND `name` NOT LIKE 'FolderOne/%/%'
这将为我提供正确的文件夹:
id name
4 FolderOne/FolderOneOne
7 FolderOne/FolderOneTwo
当我尝试确定这些文件夹是否包含任何子文件夹时,问题就开始了。
我设计MySQL查询的最佳尝试导致性能极慢。
添加到上面的查询:
SELECT f1.*, (
SELECT count(f2.id)
FROM folder AS f2
WHERE f2.account_id = 2
AND f2.`name` LIKE concat(f1.`name`, '/%')
AND f2.`name` NOT LIKE concat(f1.`name`, '/%/%')
) AS child_count
FROM folder AS f
WHERE f1.account_id = 2
AND f1.`name` LIKE 'FolderOne/%'
AND f1`name` NOT LIKE 'FolderOne/%/%'
这也会给我一个合适的文件夹:
id name child_count
4 FolderOne/FolderOneOne 2
7 FolderOne/FolderOneTwo 2
这只会在少数记录上执行得相当快。在具有1461条记录的文件夹上使用此查询将花费大约88.68秒,这是不可行或不可用的。
使用此分层结构,是否有更好(更快)的方法来确定文件夹是否包含子文件夹。如果我可以快速确定(可能很大)一组文件夹是否包含子文件夹,那么我将能够设计一种通过用户界面显示这些文件夹的正确方法。