简单查询 更新啦!
原贴 [js] 简单查询,让数据从此不再难查,支持显示多字段多视图
0.0.2 带来了新功能,可以用用 SQL 查询数据库和表格!
另外,简单查询教程 1.0 发布啦!
安装
- 首先安装简单查询 js,到这里下载 https://gitee.com/wish163/mysoft/blob/main/%E6%80%9D%E6%BA%90/SQL%E7%AE%80%E5%8D%95%E6%9F%A5%E8%AF%A2.js?utm_source=ld246.com 放到思源 js 代码片段中即可。
- 然后安装简单查询 alasql 扩展,到这里下载 https://gitee.com/wish163/mysoft/blob/main/%E6%80%9D%E6%BA%90/SQL%E7%AE%80%E5%8D%95%E6%9F%A5%E8%AF%A2.alasql.js 放到思源 js 代码片段中即可。
- 编辑器输入 {{}} ,在弹出框中输入下面的示例代码就可以使用了。
用 SQL 查询数据库
比如有个名为 demo201 数据库
通过 SQL 查询如下
//!js
return query("select `序号` as `序号__w80_c:blue_0`, `内容` from ? limit 2", [fromAv('demo201'),item]);
结果:
这个 SQL 的含义是从数据库 demo201 中查询序号和内容字段,筛选前 2 条记录,并设置序号字段 80px 宽度,蓝色文字,排序到最前面。
`序号` as `序号__w80_c:blue_0` 中,为什么序号要加反撇号`,这是 SQL 语法,由于本功能使用了 alasql 扩展(注意是简单查询 js 的扩展,不是思源的插件),在 alasql 中不支持中文字段,中文字段需要加反撇号`。
w80 意思是该字段宽度为 80px,这是简单查询语法,称为字段标记符,可参考帖子 ,w 也可以写成 width, w 是简写,80 也可以写成 80px, 80em 等。
c:blue 意思是字段显示为蓝色,同样是简单查询语法,c 是 color 的意思,也可以写成 color,blue 也可以写成#00f。
最后的 0 是代表该字段排序编号,数字越小越靠前。
字段名和标记符之间用__隔开,标记符之间用_隔开。
注意,这里与简单查询语法不同的是
- 查询的表在 SQL 中用?号表示,然后用数组传入?号代表的真实数据,比如这里的 fromAv('xxx'),从数据库查询,这里的 xxx 可以是数据库的块 id,数据库 id,数据库名,系统会智能判断你输入的参数。
类似的还有,fromTable('xxxx')
从表格查询,xxxx 是表格的块 id,fromSql('sql语句')
从 SQL 查询,即从 sqlite 中查询数据 - 原来简单查询的 item 参数现在变为了为 SQL 传递变量的数组,item 需要放到数组的最后面即可,比如这里的
[fromAv('demo201'), item]
这也好理解,原来是 item,现在需要有新成员加入了,如果不想新增参数的话,只有让房间隔开多个成员居住了,这里就是数组啦。
用 SQL 查询表格
基本查询
表格数据:
sql:
//!js
return query("select `aa` as `aa__w80_c:blue_0`, `bb` from ? where aa>55", [fromTable('20250110154352-pdr5v3t'),item]);
结果:
该 SQL 查询 aa 字段的值大于 55 的,并把 aa 字段设置为 80px 宽度,蓝色,排序到前面
汇总统计
sql:
//!js
return query("select sum(aa) as `aa列总和__w150` from ?", [fromTable('20250110154352-pdr5v3t'),item]);
结果:
该 SQL 汇总 aa 列,并重命名为“aa 列总和”,然后用 sum 函数汇总总和,并把列宽设为 150px。
更新表格
如果想汇总后更新原表格可以吗?
可以,比如,下面演示对上述表格 aa 列汇总总和后并插入一行新数据到原表格。
使用 SQL 统计:
//!js
try {
return query("select * from ?", [fromTable('20250110154352-pdr5v3t'), item], '',
async ({ rawData, updateTable, renderSuccess }) => {
let sumAA = await query("select sum(aa) as total_aa from ? WHERE isNumeric(aa)", [fromTable('20250110154352-pdr5v3t'), null]);
sumAA = sumAA[0]?.total_aa || 0;
const hasTotal = (rawData[rawData.length - 1].aa + '').indexOf('合计') !== -1;
const newIndex = hasTotal ? rawData.length - 1 : rawData.length;
if (!rawData[newIndex]) rawData[newIndex] = {};
rawData[newIndex].aa = '合计: ' + sumAA;
rawData[newIndex].bb = '';
rawData[newIndex].cc = '';
updateTable('20250110154352-pdr5v3t', rawData);
return renderSuccess('统计成功', item);
}
);
} catch (e) {
console.error(e);
return [];
}
这里加了 try{} catch(e) {} 但这不是必须的,当你的结果没有达到预期且没有报错时,可以尝试用 try 看看有没有什么报错信息。之所以要自己加 try 是因为思源拦截了错误信息。
这个 SQL 复杂的地方在于动态更新表格新行,且不影响旧数据,真正的统计就一行 sql 代码。
SQL 中的 isNumeric 这个函数并不是 alasql 自带的,而是自己定义的。扩展查询函数可以用 alasql.fn.xxx = ()=>{}扩展。也可以在简单查询用户自定义函数区定义函数,然后添加到 alaSqlFuncs
变量中即可。也可以通过 query(':regAlaSql:funcName', ()=>{})进行注册或在 alasql 扩展中等待 alasql.js 加载完成时注册。
注意,data 中新增行数据可能引起发嵌入块更新,从而再次新增行数据,引起死循环,所以这里推荐用 rawData 进行更新操作。
使用 js 统计:
//!js
return query("select * from ?", [fromTable('20250110154352-pdr5v3t'), item], '', ({ rawData, updateTable, renderSuccess }) => {
const sumAA = rawData.reduce((total, item) => total + (parseFloat(item.aa)||0), 0);
const hasTotal = (rawData[rawData.length-1].aa+'').indexOf('合计') !== -1;
const newIndex = hasTotal ? rawData.length-1 : rawData.length;
if(!rawData[newIndex]) rawData[newIndex] = {};
rawData[newIndex].aa = '合计: '+sumAA;
rawData[newIndex].bb='';
rawData[newIndex].cc='';
updateTable('20250110154352-pdr5v3t', rawData);
return renderSuccess('统计成功', item);
});
这里用 js reduce 函数统计,其他同上。
结果:
你可能会吐槽,感觉并不简单。其实并不是的,统计很简单,无论 SQL 还是 js,一句代码就能统计了。如果没用这个查询,做这个统计就复杂了。
这里显得复杂的原因是因为要新增表格数据行,如果添加列会简单许多。
新增行要考虑哪些?
- 多次更新,合计不会不停的新加行
- 如果有些行数据不是数字怎么办?
- 第一次操作要新增,后面再次操作要更新,要实时计算最后一列的索引
- 统计时要去掉合计这个单元格等
所以,以上让代码变复杂了,而统计本身很简单,如果不是更新表本身,而是简单输出就没这些问题,比如上面的汇总总和,一句 SQL 就搞定了,这在以往实现起来很复杂的。
之所以选择这个复杂的例子,主要为了说明问题及提醒注意事项。
连表查询
还可以连表查询,不仅仅表格之间,数据库之间和 sqlite 之间都可以连查。
比如
查询代码:
//!js
return query("select a.id as id__w80_0, a.*,b.* from ? as a left join ? as b on a.id = b.id", [fromTable('20250111031121-dzax849'), fromTable('20250111063241-zit8y6r'), item]);
数据统计和汇总
用 SQL 对数据库统计更方便。
参考上面的表格统计和汇总,数据库也是类似的,不再赘述。
在模板中使用
这个查询也可以在模板中使用。
在文档模板中使用
与在嵌入块中查询类似,只要转换为模板嵌入代码即可,可参照上面的示例。
关于 SQL 代码和模板代码的转换可参考 思源能否在模板中发网络请求爬取数据呢? - wilsons 的回帖
在数据库模板中使用
利用数据库模板中的 img 标签,还可以在数据库模板中使用。
可参考 思源如何给日记模板添加天气 帖子中的第二点。
说明:虽然模板中可以使用,但使用较为复杂,如果想更新数据,需要配合数据库 api 进行操作。因此建议数据库统计在数据库外部进行比较合适。
当然,如果有兴趣研究的可提供一些思路,一是用思源 api,二是用 dom 操作,如果同一个文档的话,三是使用 getAttributeView
api 或直接读取 json 文件,然后直接对 json 对象进行行或列操作,完成后再写入文件,这样反而简单许多。
自定义用法
如果你想使用 alasql 更多用法,封装的 query 查询不能满足你的需要。
也可以直接用 alasql 查询,只要把查询结果传给 query 函数的第一个参数即可。
比如,
//!js
return (async ()=>{
return query(alasql("select `序号` as `序号__w80_c:blue_0`, `内容` from ? limit 2", [await fromAv('demo201', true)]), item);
})();
这里 alasql 中也可以使用字段标记符。
注意,这里加了立即函数,这是因为思源嵌入块函数体中不能直接用异步函数,必须再封装一层,因为这里 fromAv 要读取数据,因此用了 await 且加了第一个参数 true,表示真正读取数据。而用 query 查询时,在思源嵌入块函数体内时并没有真正的查询数据,只有进入 query 函数才真正的查询,这是为了在嵌入块函数体中,让 query 函数不用再封装一层立即函数。
常见问题
偶尔可能出现 query 未定义情况,虽然很少出现。这是因为,如果刷新页面时,刚好当前文档中有嵌入块 js,思源代码片段并不能保证一定在嵌入块执行前加载完毕,所以才出现这个错误。
不过,通常影响不大,如果有问题,关闭文档重新打开就好了,或者按 f5 刷新下。
正确的方式应该是在嵌入块查询 js 中等待 query 加载完毕后执行或者设置一定的延迟,不过,由于这个问题极少出现,且影响不大,一般不用特别去处理,如果偶尔出现错误,知道原因及如何处理就好了。
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于