Wilson@思源

目 录

筛查指路径和指定列表的任务

see https://ld246.com/article/1734858211967

筛选指定路径和指定列表的任务

如果仅用 SQL 实现的话,主要带有子任务的父任务不好处理。
我这里通过取巧的方式实现了仅 SQL 查询,需要一段 css 配合一下,原理就是把指定 SQL 的子任务给隐藏起来。
SQL1:在路径内随机索引单个任务项
sql
-- random-task-hpath 这里的注释不要删除且必须再第一行且必须--开头且不能有空格 SELECT * FROM blocks WHERE ( -- 👇这里可以添加更多路径,可在目录右键复制可读路径获取 hpath like '%/daily note/2024/12/111%' OR hpath like '%/daily note/2024/12/111%' ) AND type = 'i' AND subtype = 't' -- 这里可以修改任务状态👇,注意[X]中的X必须是大写,[ ]中有个英文空格,可以复制这注释里的 AND markdown like '%* [ ] %' || TRIM(fcontent) || '%' ORDER BY RANDOM() LIMIT 1;
SQL2:在列表内随机索引单个任务项
sql
-- radmom-task-list 这里的注释不要删除且必须再第一行且必须--开头且不能有空格 WITH RECURSIVE Descendants AS ( -- 非递归部分,这是起始查询,选择指定id的初始记录 SELECT * FROM blocks WHERE id in( -- 👇这里可以添加更多列表id '20241222170944-o65g6ol', '20241222170955-k3mt4vd' ) UNION ALL -- 递归部分,将子记录不断加入结果集 SELECT b.* FROM blocks b JOIN Descendants d ON b.parent_id = d.id ) SELECT * FROM Descendants WHERE type = 'i' AND subtype = 't' -- 这里可以修改任务状态👇,注意[X]中的X必须是大写,[ ]中有个英文空格,可以复制这注释里的 AND markdown like '%* [ ] %' || TRIM(fcontent) || '%' ORDER BY RANDOM() LIMIT 1;
css 代码:
css
/* 隐藏指定SQL的嵌入块中的子任务 */ [data-type="NodeBlockQueryEmbed"][data-content^="-- random-task-hpath"], [data-type="NodeBlockQueryEmbed"][data-content^="-- radmom-task-list"]{ [data-subtype="t"]:not([data-marker="*"]) { display:none; } }
说明:SQL 前面的 -- random-task-hpath​ 和 -- radmom-task-list​ 注释不要删除,这是 css 定位元素的标志。
不知是否是你想要的需求,我简单测试了下没发现问题,不知是否存在潜在问题,如果有问题可以随时反馈。
效果:

筛选任务状态

如果需要筛选 [X]​ 和 [ ]​ 状态可以按照下面的方式添加到条件里即可。 添加到这两个条件后面就行 WHERE type = 'i' AND subtype = 't'
比如
sql
select * from blocks -- (其他SQL) WHERE type = 'i' AND subtype = 't' -- 匹配已选中的 AND markdown like '* [X]%' -- 匹配未选中的 AND markdown like '* [ ]%' -- 以上SQL一般没有问题,仅匹配第一个任务,能有效避免误选子任务 -- 如果有问题,也可以用下面的方式,更安全,但稍麻烦 -- 匹配已选中的,注意[X]中的X必须是大写,[ ]中有个英文空格 AND markdown like '%* [X] %' || TRIM(fcontent) || '%' -- 匹配未选中的,注意[X]中的X必须是大写,[ ]中有个英文空格 AND markdown like '%* [ ] %' || TRIM(fcontent) || '%' ORDER BY RANDOM() LIMIT 1;

SQL的UNION ALL原理说明

例如,假设我们有如下简单的 blocks​ 表数据(为了方便示例简化了数据结构和实际值,用数字表示 id​ 和 parent_id​ 等):
idparent_idtypesubtypecontent
10'i''t''a'
21'i''t''b'
32'i''t''c'
40'x''y''d'
并且我们设定起始查询的 id​ 列表为 (1)​(就像你代码里实际指定那两个复杂 id​ 一样,这里简化为 1​ 方便举例)。
第一步:非递归部分会找到 id​ 为 1​ 的记录,也就是 (1, 0, 'i', 't', 'a')​ 这条记录,这是起始节点。
第二步:进入递归部分,此时 Descendants​ 里就只有刚才找到的 id​ 为 1​ 的那条记录。然后查询会去 blocks​ 表中找 parent_id​ 等于 1​ 的记录,会找到 id​ 为 2​ 的记录(因为它的 parent_id​ 是 1​),这样 id​ 为 2​ 的记录就被加入到 Descendants​ 结果集中了,此时 Descendants​ 包含 id​ 为 1​ 和 2​ 的记录。
第三步:再次进行递归查找,因为 Descendants​ 现在有 id​ 为 1​ 和 2​ 的记录了,会继续查找 blocks​ 表中 parent_id​ 为 2​ 的记录(基于刚才新加入的 id​ 为 2​ 的记录),会找到 id​ 为 3​ 的记录并加入到 Descendants​ 中,现在 Descendants​ 包含 id​ 为 1​、2​、3​ 的记录了。
第四步:继续递归查找,发现没有新的符合 parent_id​ 匹配条件的记录了,递归结束,Descendants​ 最终包含了 id​ 为 1​、2​、3​ 的记录,这就是以 id​ 为 1​ 的记录为起始节点的所有后代记录。
递归后的结果集是什么,与递归前有什么不同?
以下是以之前假设的 blocks​ 表数据为例,展示递归前后结果集的情况:

递归前(非递归部分找到的起始节点)

在非递归部分,我们设定起始查询的 id​ 为 1​,所以找到的起始节点记录如下表所示:
idparent_idtypesubtypecontent
10'i''t''a'

递归后(最终 Descendants​ 结果集)

经过递归查找所有后代节点的操作后,Descendants​ 结果集如下表所示:
idparent_idtypesubtypecontent
10'i''t''a'
21'i''t''b'
32'i''t''c'
可以看出,递归前只有最初指定的起始节点记录(id​ 为 1​ 的那条),而递归后通过不断查找子记录(基于 parent_id​ 和已有记录 id​ 的关联匹配),将 id​ 为 1​ 的记录的所有后代记录(这里是 id​ 为 2​ 和 3​ 的记录,因为 2​ 的父节点是 1​,3​ 的父节点是 2​)都加入到了结果集中,这就是递归操作带来的结果集的变化,实现了从一个或多个起始节点向下查找所有相关后代节点的效果。
如果在实际情况中,你的表结构更复杂、数据更多,按照同样的逻辑,会不断地把符合条件的后代记录一层一层地添加进来,直到没有新的子记录可添加为止。