集算器如何优化SQL计算(3)序运算_MySQL
跨行引用
早期SQL不直接支持跨行引用,要生成序号后再JOIN,极其繁琐困难。引入窗口函数后的SQL能够较方便地引用其它行数据,但写法仍不简洁,有多个跨行引用项时代码会很长。而且如前所述,窗口函数在其它运算结果集基础上再实施,对窗口函数计算值的再引用就要写成子查询的形式,仍然繁琐。
MySQL不支持窗口函数,但支持在SQL中使用变量,可以引用到前面的行,但无法引用到后面的行。
集算器提供了方便自然的跨行引用语法。
各产品月销售表结构为:产品、月份、销量;现要找出销量比上月多10%的记录。
|
A |
1 |
=db.query("select * from 销售表 order by 产品,月份") |
2 |
=A1.select(if(产品==产品[-1],销量/销量[-1])>1.1) |
排序后可以简单用[-1]就可以引用前一月的数据,且可以直接基于跨行计算值过滤。使用SQL窗口函数则要用子查询,MySQL则要定义两个临时变量。
再计算上表中各月前后一个月的销量移动平均值:
|
A |
1 |
=db.query("select * from 销售表 order by 产品,月份") |
2 |
=A1.derive(if(产品==产品[-1]&&产品==产品[1],销量{-1:1}.avg()):移动平均) |
计算移动平均涉及到向后引用和集合引用,用[1]可引用下一行数据,{-1:1}可引用从上一行到下一行的字段值集合。类似地,SQL窗口函数也需要子查询先把相应行计算出来再做移动平均;而MySQL的变量不能后向引用,就很难直接计算了。
再看一例,简化的事件表结构为:序号,时刻,…;时刻应当和序号同步递增,但可能有错误,需要找出时刻没有和序号同步递增的记录。
|
A |
|
1 |
=db.query("select * from 事件表 order by 序号") |
|
2 |
=A1.select(时刻!=max(时刻{:0})||时刻!=min(时刻{0:})) |
和前后所有记录对比 |
取集合时还可以从头取后或取到尾。SQL窗口函数也支持类似的写法,但两次比较要做两个不同方向的排序,当然了必须要用子查询。
有序分组
SQL只提供与次序无关的等值分组,但有时分组的键值并不能在每条记录中找到,而是和记录的次序有关,这种情况,用SQL又需要使用窗口函数(或其它更麻烦的手段)制造出序号才能实现。
集算器提供了与次序相关的分组机制,方便用于与连续区间相关的计算。
收支表结构为:月份、收入、支出;找出连续亏损达三月或以上的那些月份的记录。
|
A |
1 |
=db.query("select * from 收支表 order by 月份") |
2 |
=A1.group@o(收入>支出).select(~.收入 |
group@o表示在分组时只比较相邻记录,如果相邻值发生变化则会分出一个新组。这样就可以根据收入支出的比较把收支记录分成赢利、亏损、赢利、…这样的组,然后取出其中亏损且成员不少于3的组再合并起来。
还是这个表,希望计算收入最长连续增长了几个月。可以设计这样的分组机制:收入增长时和上月分作一个组,收入下降时则分出一个新组,最后统计组成员的最大值。
|
A |
1 |
=db.query("select * from 收支表 order by 月份") |
2 |
=A1.group@i(收入<收入[-1]).max(~.len()) |
group@i将在条件变化时分出一个新组,即收入降低时。
在窗口函数的支持下,SQL也能实现本例和上例的思路,但写法非常难懂。
区间合并也是常见的有序分组运算。设有事件发生区间表T有字段:S(开始时刻)、E(结束时刻);现在要将这些区间中重叠部分去除后再计算该事件实际发生的总时长。
| A |
|
1 | $select S,E from T order by S |
|
2 | =A1.select(E>max(E{:-1})) |
去除被包含的条目 |
3 |
=A2.run(max(S,E[-1]):S) |
去除重叠时间段 |
4 |
=A2.sum(interval@s(max(S,E[-1]),E)) |
计算总时长 |
5 |
=A2.run(if(S | 合并有重叠的时间段 |
这里给了多种目标的处理方法,充分利用了跨行运算和有序分组的特点。SQL要实现这种运算简单用窗口函数已经做不到了,需要用到很难理解的递归查询。
位置访问
对于有序的集合,有时我们需要直接用序号访问成员。SQL延用了数学上的无序集合概念,要生成序号再用条件过滤才能访问指定位置的成员,这对许多运算造成很大的麻烦。
集算器采用了有序集合机制,允许直接用序号访问成员,这类运算要方便得多。
比如经济统计中常用到的在众多价格中找出中位数:
| A |
1 | =db.query@i("select 价格 from T order by 价格") |
2 | =A1([(A1.len()+1)\2,A1.len()\2+1]).avg() |
位置还可以用于分组。事件表结构为:序号、时刻、动作,动作有开始、结束两种,现在要统计事件持续的总时长,即每一对开始和结束之间的时间之和。
| A |
1 | =db.query@i("select 时刻 from 事件表 order by 时刻") |
2 | =A1.group((#-1)\2).sum(interval@s(~(1),~(2)) |
#表示记录序号,group((#-1)\2)即将数据每两个分成一组,然后针对每组计算时长再合计即可。
根据位置还能进行相邻跨行引用。设有股价表结构为:交易日、收盘价;现列出计算出股价超过100元的交易日及当日涨幅。
| A |
1 | =db.query("select * from 股价表 order by 交易日") |
2 | =A1.pselect@a(收盘价>100).select(~>1) |
3 |
=A2.new(A1(~).交易日:交易日,A1(~).收盘价-A1(~-1).收盘价:涨幅) |
pselect函数将返回满足条件的成员位置,使用这些位置就可以方便地计算涨幅,而不必象使用窗口函数时事先计算出所有涨幅再过滤。
---恢复内容结束---
以上就是集算器如何优化SQL计算(3)序运算_MySQL的内容,更多相关内容请关注PHP中文网(www.php.cn)!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

熱門話題

MySQL適合初學者使用,因為它安裝簡單、功能強大且易於管理數據。 1.安裝和配置簡單,適用於多種操作系統。 2.支持基本操作如創建數據庫和表、插入、查詢、更新和刪除數據。 3.提供高級功能如JOIN操作和子查詢。 4.可以通過索引、查詢優化和分錶分區來提升性能。 5.支持備份、恢復和安全措施,確保數據的安全和一致性。

Navicat本身不存儲數據庫密碼,只能找回加密後的密碼。解決辦法:1. 檢查密碼管理器;2. 檢查Navicat的“記住密碼”功能;3. 重置數據庫密碼;4. 聯繫數據庫管理員。

使用 Navicat Premium 創建數據庫:連接到數據庫服務器並輸入連接參數。右鍵單擊服務器並選擇“創建數據庫”。輸入新數據庫的名稱和指定字符集和排序規則。連接到新數據庫並在“對象瀏覽器”中創建表。右鍵單擊表並選擇“插入數據”來插入數據。

通過以下命令查看 MySQL 數據庫:連接到服務器:mysql -u 用戶名 -p 密碼運行 SHOW DATABASES; 命令獲取所有現有數據庫選擇數據庫:USE 數據庫名;查看表:SHOW TABLES;查看表結構:DESCRIBE 表名;查看數據:SELECT * FROM 表名;

在 MySQL 中復製表需要創建新表、插入數據、設置外鍵、複製索引、觸發器、存儲過程和函數。具體步驟包括:創建具有相同結構的新表。將數據從原始表插入新表。設置相同的外鍵約束(如果原始表有)。創建相同索引。創建相同觸發器(如果原始表有)。創建相同存儲過程或函數(如果原始表使用了)。

Navicat for MariaDB 無法直接查看數據庫密碼,因為密碼以加密形式存儲。為確保數據庫安全,有三個方法可重置密碼:通過 Navicat 重置密碼,設置複雜密碼。查看配置文件(不推薦,風險高)。使用系統命令行工具(不推薦,需要對命令行工具精通)。

MySQL 中的複制粘貼包含以下步驟:選擇數據,使用 Ctrl C(Windows)或 Cmd C(Mac)複製;在目標位置右鍵單擊,選擇“粘貼”或使用 Ctrl V(Windows)或 Cmd V(Mac);複製的數據將插入到目標位置,或替換現有數據(取決於目標位置是否已存在數據)。

在 Navicat 中執行 SQL 的步驟:連接到數據庫。創建 SQL 編輯器窗口。編寫 SQL 查詢或腳本。單擊“運行”按鈕執行查詢或腳本。查看結果(如果執行查詢的話)。
