SQL 后计算的利器 SPL

2023-11-19

现代应用开发中,通常只用SQL实现简单的数据存取动作,而主要的计算过程和业务逻辑直接在应用程序中实现,主要原因在于:

  • 过于复杂的SQL很难调试、编写、阅读、修改。
  • SQL有方言特征,大量使用SQL后,会导致程序很难移植。
  • 架构方面要求业务逻辑在应用中实现,而不能依赖于数据库,否则耦合性过高。
  • 有些计算SQL不擅长,包括复杂的集合计算、有序计算、关联计算、多步骤计算,经常也需要移到数据库外实现。
  • 实现流程控制时,因为更难移植、耦合性更高、影响数据安全,不方便使用存储过程。

此外,还有涉及多数据库和非数据库的场景,也无法使用SQL完成计算任务,只能在外部完成。

这样,就要在应用程序中实现SQL后计算任务。

SQL返回的数据一般都是结构化数据,那么好的SQL后计算技术也要有方便的结构化数据对象,能够进一步计算和处理返回的数据;提供丰富的库函数,拥有不亚于SQL的计算能力;最好还能支持循环和判断语法以实现流程控制。特别地,SQL后计算技术要用在应用程序中,要易于被集成。

Java是重要的开发语言,但JDK提供的方法过于基础,虽然能实现SQL后计算,但开发效率很低。

ORMJava中用来实现SQL后计算的常见方案。但几种较流行的ORM都缺乏专业的结构化数据对象,不支持动态数据结构。虽然可以利用Java实现流程控制,但难以进行灵活的计算。这些ORM技术的计算能力还远不如SQL,提供的计算函数非常有限,用Java硬写的现象仍然非常普遍。

Stream的链式编程比ORMHQL更加面向对象,且有Lambda语法的加成,也常被用于SQL后计算,有些ORM还能直接生成Stream对象。但Stream同样没有专业的结构化数据对象,不支持动态数据结构。此外,Stream的计算能力也较差,甚至不如ORM,即使排序、分组汇总、关联这样的基础计算,也要辅以大量编码。

Kotlin基于JVM,且在链式编程和Lambda语法上对Stream进行了一系列改进,也可以用于SQL后计算。但因为编译型语言的底层,Kotlin只能对Stream小幅微调,重大缺点一个没少。

Python Pandas有较强大的结构化数据处理能力,有时也可以用于SQL后计算,但因为缺乏易用的接口,很难被Java集成,很少出现在正式项目中。

esProc SPL是更好的SQL后计算技术。

专业的结构化数据对象

SPLJVM下的开源结构化数据计算引擎,内置专业的结构化数据对象序表,可以和数据库表/记录方便地互转,支持动态数据结构,提供了灵活易用的访问方法、维护方法、计算函数。序表专业性强,为数据计算和流程控制提供了有力的底层支撑,可以方便地实现SQL后计算中的各类业务逻辑。

直接的数据库交换方法,可以在数据库表(SQL结果集)和SPL序表之间进行互转。

比如,使用query函数执行SQL,生成单条记录序表:

A B
1 =connect("orcl") //连接数据库
2 .query("select * from sales where orderid=?",201)=r=A1 //查询单条记录
3 =db.close() //关闭数据库连接

如果SQL返回多条记录,则自动生成多条记录序表:

=T=A1.query("select * from salesR where SellerID=?",10)

反过来也简单,用update函数就可以将序表记录批量地持久化到数据库。比如,原序表为T,经过多条件记录的增删改之后的序表为NT,将两者的变更结果统一写入数据库:

=A1.update(NT:T,sales;ORDERID)

灵活的序表访问方法,可以按字段名或记录号自由地访问序表。

取序表的第3条记录:T(3)

取后3条记录:T.m([-1,-2,-3])

取记录的字段值:T(3).Amount*0.05

取一列,返回集合:T.(Amount)

取几列,返回集合的集合:T.([CLIENT,AMOUNT])

先按字段名取再按记录序号取:T.(AMOUNT)(3)

先按记录序号取再按字段名取:T(3).AMOUNT

易用的序表维护方法,可以对单条或多条记录记录进行统一的增删改操作。

追加记录:T.insert(200,"APPL",10,2400.4,date("2010-10-10"))

修改记录:T(3).Amount = T(3). Amount*1.05

删除记录:T.delete(T.select(ORDERID\==209 || ORDERID==208))

丰富的序表计算函数,可进行完整的SQL式计算。

过滤:T.select(Amount>1000 && Amount<=3000 && like(Client,"*bro*"))

排序:T.sort(-Client,Amount)

去重:T.id(Client)

汇总:T.max(Amount)

分组汇总后过滤: T.groups(year(OrderDate),Client; avg(Amount):amt).select(amt>2000)

关联:join(Orders:o,SellerId ; Employees:e,EId).groups(e.Dept; sum(o.Amount))

交集:T1.id(Client) ^ T2.id(Client)

TopN:T.top(-3;Amount)

分组topN:T.groups(Client;top(3,Amount))

支持动态数据结构,可根据上一步的计算结果推断出新数据结构,并自动生成新序表,新序表可直接进行计算。比如先分组汇总,再过滤,最后排序:

T.groups(SellerId, Client; sum(Amount):amt, count(1):cnt).select(amt>10000 && amt<=30000 && like(Client,"\*bro*")).sort(amt)

使用支持动态数据结构的序表,开发者可以更加关注计算本身,而不是思考如何事先定义结果集。这样的编码风格不仅简短易懂,而且更符合自然思维,开发效率可以显著提升。在多步骤的复杂业务逻辑中,动态数据结构带来的优势更加明显。

强大的结构化数据计算能力

SPL提供了多种方便易用的语法,内置大量功能强大的函数,可以简化复杂的有序运算、集合运算、分布计算、关联计算。很多用SQL和存储过程难以表达的计算,用SPL都可以轻松实现。

函数选项、层次参数等方便的语法,功能相似的函数可以共用一个函数名,只用函数选项区分差别,比SQL更加灵活方便。比如select函数的基本功能是过滤,如果只过滤出符合条件的第1条记录,可使用选项@1:

T.select@1(Amount>1000)

并行过滤,适合数据量较大的情况,使用选项@m:

T.select@m(Amount>1000)

二分法排序,即对有序数据用二分法进行快速过滤,使用@b:

T.select@b(Amount>1000)

有序分组,即对分组字段有序的数据,将相邻且字段值相同的记录分为一组,使用@b:

T.groups@b(Client;sum(Amount))

函数选项还可以组合搭配,比如:

Orders.select@1b(Amount>1000)

结构化运算函数的参数有些很复杂,比如SQL就需要用各种关键字把一条语句的参数分隔成多个组,但这会动用很多关键字,也使语句结构不统一。SPL使用层次参数简化了复杂参数的表达,即通过分号、逗号、冒号自高而低将参数分为三层:

join(Orders:o,SellerId ; Employees:e,EId)

内置大量日期函数和字符串函数,在数量和功能上远远超过其他技术甚至SQL,同样的运算代码量更短。比如:

时间类函数,日期增减:elapse("2020-02-27",5) //返回2020-03-03

星期几:day@w("2020-02-27") //返回5,即星期4

N个工作日之后的日期:workday(date("2022-01-01"),25) //返回2022-02-04

字符串类函数,判断是否全为数字:isdigit("12345") //返回true

取子串前面的字符串:substr@l("abCDcdef","cd") //返回abCD

按竖线拆成字符串数组:"aa|bb|cc".split("|") //返回["aa","bb","cc"]

SPL还支持年份增减、求年中第几天、求季度、按正则表达式拆分字符串、拆出SQL的where或select部分、拆出单词、按标记拆HTML等功能。

简化复杂的有序运算。涉及跨行的有序运算,通常都有一定的难度,比如比上期和同期比。SPL使用"字段[相对位置]"引用跨行的数据,可显著简化代码,还可以自动处理数组越界等特殊情况,经常比SQL更方便。比如,追加一个计算列rate,计算每条订单的金额增长率:

=T.derive(AMOUNT/AMOUNT[-1]-1: rate)

综合运用位置表达式和有序函数,很多SQL难以实现的有序运算,都可以用SPL轻松解决。比如,根据考勤表,找出连续 4 周每天均出勤达 7 小时的学生:

A
1 =connect("mysql")
2 =A1.query@x("SELECT SID,ATTDATE,DURATION,null AS W FROM STUTEST WHERE DURATION>=7 ORDER BY SID,ATTDATE").run(W=pdate@w(ATTDATE))
3 =A2.group@o(SID;~.groups@o(W;count(~):CNT).select(CNT==7).group@i(W-W[-1]!=7).max(~.len()):weeks)
4 =A3.select(weeks>=4).(SID)

简化复杂的集合运算,SPL序表的集合化更加彻底,配合灵活的语法和强大的集合函数,可大幅简化复杂的集合计算。比如,在各部门找出比本部门平均年龄小的员工:

A
1 …//省略序表Employees的生成过程
2 =Employees.group(DEPT; (a=~.avg(age(BIRTHDAY)),~.select(age(BIRTHDAY)<a)):YOUNG)
3 =A2.conj(YOUNG)

计算某支股票最长的连续上涨天数:

A
1 …//省略序表AAPL的生成过程
2 =a=0,AAPL.max(a=if(price>price[-1],a+1,0))

SPL可以方便地实现分步计算,序表的集合化更加彻底,可以用变量方便地表达集合,适合多步骤计算,很多SQL难以表达的集合运算,用SPL都可以轻松实现。比如,找出销售额累计占到一半的前n个大客户,并按销售额从大到小排序:

A B
1 //省略取数据的过程
2 =A1.sort(amount:-1) /销售额逆序排序,可在SQL中完成
3 =A2.cumulate(amount) /计算累计序列
4 =A3.m(-1)/2 /最后的累计即总额
5 =A3.pselect(~>=A4) /超过一半的位置
6 =A2(to(A5)) /按位置取值

简化复杂的关联计算。序表的专业性体现在多方面,其中之一是支持对象引用的形式表达关联,开发者可以通过点号直观地访问关联表,从而提高开发效率。很多SQL难以表达的关联计算,用SPL都可以轻松实现。比如,根据员工表计算女经理的男员工:

=employees.select(gender:"male",dept.manager.gender:"female")

灵活的流程控制能力

SPL提供了灵活易用的分支判断语句、循环语句,配合专业的结构化数据对象,可以方便地实现各类业务逻辑。

分支判断语句

A B
2
3 if T.AMOUNT>10000 =T.BONUS=T.AMOUNT*0.05
4 else if T.AMOUNT>=5000 && T.AMOUNT<10000 =T.BONUS=T.AMOUNT*0.03
5 else if T.AMOUNT>=2000 && T.AMOUNT<5000 =T.BONUS=T.AMOUNT*0.02

循环语句

A B
1 =db=connect("db")
2 =T=db.query@x("select * from sales where SellerID=? order by OrderDate",9)
3 for T =A3.BONUS=A3.BONUS+A3.AMOUNT*0.01
4 =A3.CLIENT=CONCAT(LEFT(A3.CLIENT,4), " co.,ltd.")
5  …

与Java的循环类似,SPL还可用break关键字跳出(中断)当前循环体,或用next关键字跳过(忽略)本轮循环,不展开说了。

流程控制语句配合序表,可以用统一的语法风格实现业务逻辑,包括数据库读写、事务处理、流程处理、数据计算。比如,根据一定的规则计算奖金:

A B C
1 =db=connect@e("dbName") /连接数据库,开启事务
2 =db.query@1("select sum(Amount) from sales where sellerID=? and year(OrderDate)=? and month(OrderDate)=?", p_SellerID,year(now()),month(now())) /查询当月销售额
3 =if(A2>=10000 :200, A2<10000 && A2>=2000 :100, 0) /本月累计奖金
4 =p_Amount*0.05 /本单固定奖金
5 =BONUS=A3+A4 /总奖金
6 =create(ORDERID,CLIENT,SELLERID,AMOUNT,BONUS,ORDERDATE) /创建订单的数据结构
7 =A6.record([p_OrderID,p_Client,p_SellerID,p_Amount,BONUS, date(now())]) /生成一条订单记录
8 >db.update@ik(A7,sales;ORDERID) /尝试写入库表
9 =db.error() /入库结果
10 if A9==0 >A1.commit() /成功,则提交事务
11 Else >A1.rollback() /失败,则回滚事务
12 >db.close() /关闭数据库连接
13 return A9 /返回入库结果

优化体系结构

SPL支持JDBC接口,代码可外置于Java,耦合性更低。SPL具有解释执行的特性,支持库外计算和代码移植,支持跨库跨源计算,在SQL后计算中可提供良好的架构性。

SPL提供了易用的JDBC接口,可被Java代码无缝集成。比如,将前面的SPL代码存为脚本文件,再在Java中以存储过程的形式调用文件名:

Class.forName("com.esproc.jdbc.InternalDriver");
Connection connection =DriverManager.getConnection("jdbc:esproc:local://");
Statement statement = connection.createStatement();
ResultSet result = statement.executeQuery("call writeBonus()");

SPL代码外置于Java,通过文件名被调用,既不依赖数据库,也不依赖Java,业务逻辑和前端代码分离,耦合性低。

解释执行和热切换。业务逻辑数量多,复杂度高,变化是常态。良好的系统构架,应该有能力应对变化的业务逻辑。ORM的本质是Java代码,需要先编译再执行,一般都要停机才能部署,应对变化的业务逻辑时非常繁琐。SPL是基于Java的解释型语言,无须编译就能执行,脚本修改后立即生效,支持不停机的热切换,适合应对变化的业务逻辑。

方便代码移植。SPL通过数据源名从数据库取数,如果需要移植,只要改动配置文件中的数据源配置信息,而不必修改SPL代码。SPL支持动态数据源,可通过参数或宏切换不同的数据库,从而进行更方便的移植。为了进一步增强可移植性,SPL还提供了与具体数据库无关的标准SQL语法,使用sqltranslate函数可将标准SQL转为主流方言SQL,仍然通过query函数执行。

方便管理运营。由于支持库外计算,代码可被第三方工具管理,方便团队协作;SPL脚本可以按文件目录进行存放,方便灵活,管理成本低;SPL对数据库的权限要求类似Java,不影响数据安全。

跨库和跨源计算。SPL序表可以统一读取各类数据源(含RDB),可以用统一的代码计算各类数据源,可以方便地实现跨库计算。比如,对MySQL和Oracle进行内关联:

A
1 =mysql1.query("select SellerId, sum(Amount) subtotal from Orders group by SellerId")
2 =orcl.query("select EId,Name from employees")
3 =join(A1:O,SellerId; A2:E,EId).new(O.Name:name, O.Dept:dept, E.subtotal:amt)

SPL支持多种非RDB数据源,可进行RDB和非RDB之间的混合计算。包括txt\csv\xls等文件,MongoDB、Hadoop、redis、ElasticSearch、Kafka、Cassandra等NoSQL,以及WebService XML、Restful Json等多层数据。

ORM以及Stream/Kotlin缺乏专业的结构化数据对象和运算能力,Python Pandas难以被Java集成。SPL内置专业的结构化数据对象,具有强大的结构化数据计算能力和灵活的流程控制能力,可以方便地实现各类业务逻辑。提供了易用的JDBC接口,可以被Java方便地集成。还有更多结构性优势,包括耦合性低、解释执行和热切换、库外计算,以及跨库和跨源计算。

SPL资料

在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SQL 后计算的利器 SPL 的相关文章

  • “java.net.MalformedURLException:未找到协议”读取到 html 文件

    我收到一个错误 java net MalformedURLException Protocol not found 我想读取网络上的 HTML 文件 mainfest uses permission android name android
  • Java:在 eclipse 中导出到 .jar 文件

    我正在尝试将 Eclipse 中的程序导出到 jar 文件 在我的项目中 我添加了一些图片和 PDF s 当我导出到 jar 文件时 似乎只有main已编译并导出 我的意愿是如果可能的话将所有内容导出到 jar 文件 因为这样我想将其转换为
  • Spring Data JPA 选择不同

    我有一个情况 我需要建立一个select distinct a address from Person a 其中地址是 Person 内的地址实体 类型的查询 我正在使用规范动态构建我的 where 子句并使用findAll Specifi
  • Kotlin 未解决的参考:CLI 上 gradle 的 println

    放一个printlnkotlin 函数返回之前的语句会崩溃 堆栈跟踪 thufir dur NetBeansProjects kotlin thufir dur NetBeansProjects kotlin gradle clean bu
  • ConcurrentHashMap 内部是如何工作的?

    我正在阅读有关 Java 并发性的 Oracle 官方文档 我想知道Collection由返回 public static
  • 如何检测 Java 字符串中的 unicode 字符?

    假设我有一个包含 的字符串 我如何找到所有这些 un icode 字符 我应该测试他们的代码吗 我该怎么做呢 例如 给定字符串 A X 我想将其转换为 AYXY 我想对其他 unicode 字符做同样的事情 并且我不想将它们存储在某种翻译映
  • 从 GitHub 上托管的 Spring Cloud Config Server 访问存储库的身份验证问题

    我在 GitHub 上的存储库中托管配置 如果我将回购公开 一切都好 但如果我将其设为私有 我将面临 org eclipse jgit errors TransportException https github com my user m
  • 读取电子邮件的文本文件转换为 Javamail MimeMessage

    我有一个电子邮件原始来源的文本文件 直接从 gmail 复制 如果您单击 查看原始文件 您就会看到它 我想读入该文件并将其转换为 MimeMessage 如果您好奇为什么 我设置了 JavaMaildir 并且需要用电子邮件填充它的收件箱以
  • Java实现累加器类,提供Collector

    A Collector具有三种通用类型 public interface Collector
  • hive sql查找最新记录

    该表是 create table test id string name string age string modified string 像这样的数据 id name age modifed 1 a 10 2011 11 11 11 1
  • 如何在 Java 中创建接受多个值的单个注释

    我有一个名为 Retention RetentionPolicy SOURCE Target ElementType METHOD public interface JIRA The Key Bug number JIRA referenc
  • 使用布尔值进行冒泡排序以确定数组是否已排序

    我有以下用于冒泡排序的代码 但它根本不排序 如果我删除布尔值那么它工作正常 我知道 由于我的 a 0 小于所有其他元素 因此没有执行交换 任何人都可以帮助我解决这个问题 package com sample public class Bub
  • JMenu 中的文本居中

    好吧 我一直在网上寻找有关此问题的帮助 但我尝试的任何方法似乎都不起作用 我想让所有菜单文本都集中在菜单按钮上 当我使用setHorizontalTextPosition JMenu CENTER 没有变化 事实上 无论我使用什么常量 菜单
  • 标量子查询包含多行

    我正在使用 H2 数据库并想要移动一些数据 为此 我创建了以下查询 UPDATE CUSTOMER SET EMAIL SELECT service EMAIL FROM CUSTOMER SERVICE AS service INNER
  • 分组和切换列和行

    我不知道这是否会被正式称为枢轴 但我想要的结果是这样的 Alex Charley Liza 213 345 1 23 111 5 42 52 2 323 5 23 1 324 5 我的输入数据采用这种形式 Apt Name
  • 如何重新启动死线程? [复制]

    这个问题在这里已经有答案了 有哪些不同的可能性可以带来死线程回到可运行状态 如果您查看线程生命周期图像 就会发现一旦线程终止 您就无法返回到新位置 So 没有办法将死线程恢复到可运行状态 相反 您应该创建一个新的 Thread 实例
  • 根据由另一列分组的不同列的最大值获取值[重复]

    这个问题在这里已经有答案了 我想根据由另一列分组的不同列的最大值来获取列的值 我有这张表 KEY NUM VAL A 1 AB B 1 CD B 2 EF C 2 GH C 3 HI D 1 JK D 3 LM 并想要这样的结果 KEY V
  • org.apache.commons.net.io.CopyStreamException:复制时捕获 IOException

    我正在尝试使用以下方法中的代码将在我的服务器中创建的一些文件复制到 FTP 但奇怪的是我随机地低于错误 我无法弄清楚发生了什么 Exception org apache commons net io CopyStreamException
  • 泛型、数组和 ClassCastException

    我想这里一定发生了一些我不知道的微妙事情 考虑以下 public class Foo
  • 在java中使用多个bufferedImage

    我正在 java 小程序中制作游戏 并且正在尝试优化我的代码以减少闪烁 我已经实现了双缓冲 因此我尝试使用另一个 BufferedImage 来存储不改变的游戏背景元素的图片 这是我的代码的相关部分 public class QuizApp

随机推荐

  • Qt 集成Web 的内容

    文章目录 Qt 集成Web 的内容 Qt 中的WebEngine Qt和HTML JavaScript混合应用程序 Qt WebEngine 概述 Qt WebEngine 架构 Qt WebEngine Widgets 模块 Qt Web
  • python远程文件管理系统_python 读取远程服务器文件

    几个提高工作效率的Python内置小工具 在这篇文章里 我们将会介绍4个Python解释器自身提供的小工具 这些小工具在笔者的日常工作中经常用到 减少了各种时间的浪费 然而 却很容易被大家忽略 每当有新来的同事看到我这么使用时 都忍不住感叹
  • openvino+yolov5的检测优化及其在考勤机上的应用

    openvino yolov5的检测优化及其在考勤机上的应用 1 简介 2 安装yolov5 3 配置Pytorch环境 1 在开始界面中打开Anaconda Prompt 2 输入命令 4 配置到Pycharm 1 打开Pycharm 2
  • 多维时序

    多维时序 MATLAB实现GA GRU遗传算法优化门控循环单元多变量时间序列预测 目录 多维时序 MATLAB实现GA GRU遗传算法优化门控循环单元多变量时间序列预测 效果一览 基本介绍 程序设计 参考资料 效果一览 基本介绍 多维时序
  • ubuntu16.04踩坑笔记--ubuntu循环登录问题

    感觉自己有毒 在没有预兆的情况下 ubuntu登录界面循环登录 无法进入桌面 具体表现为登录密码输入后 黑屏一下继续回到登录界面 然后循环 在网上找到很多方法 比如 1 检查 Xauthority属于我的所有权 而不是root 包括删掉和权
  • failed to execute goal org.apache.maven.plugins:maven-archetype-plugin错误解决方法

    使用maven创建project时碰到如下错误 D codes JSF gt mvn archetype create DgroupId com tutorialspoint test DartifactId helloworld Darc
  • 把openssh升级到8.1版本

    把openssh升级到8 1版本各种坑都能解决无敌 下载相应的软件包 yum install wget gcc y yum group install Development Tools y yum install y zlib devel
  • 删除链表的倒数第n个节点

    题目 Given a linked list remove the n th node from the end of list and return its head For example Given linked list 1 gt
  • 形象易懂讲解算法II——压缩感知

    形象易懂讲解算法II 压缩感知
  • Qt5.12.2交叉编译并移植程序到ARM过程记录

    交叉编译 在系统A中编译出在要系统B中运行的环境 程序 编译工具 x9 gcc linaro 5 5 0 2017 10 x86 64 arm linux gnueabihf 1 将编译工具拷贝到 opt 文件夹 2 下载Qt源代码 解压
  • 【云原生】Docker 详解(三):Docker 镜像管理基础

    Docker 详解 三 Docker 镜像管理基础 1 镜像的概念 镜像可以理解为应用程序的集装箱 而 Docker 用来装卸集装箱 Docker 镜像含有启动容器所需要的文件系统及其内容 因此 其用于创建并启动容器 Docker 镜像采用
  • 数据结构算法—邻接表存储的无向图求连通分量个数

    数据结构算法 邻接表存储的无向图求连通分量个数 邻接表存储结构 typedef struct ArcNode int adjvex 边指向的顶点 struct ArcNode nextarc 下一条边的指针 ArcNode typedef
  • 感谢我的python老师

    Python自动化开发 金角大王版 http www cnblogs com alex3714 articles 5885096 html 转载于 https www cnblogs com tianqizhi p 8385650 html
  • canvas 流程图bug

    问题一 在当前年份点击选择没有取消调选择在去选择年份是会出bug 修改 canvas 添加点击事件后状态恢复到初始值 修改完 效果图
  • Swagger--基础--02--集成Springboot

    Swagger 基础 02 集成Springboot 代码位置 https gitee com DanShenGuiZu learnDemo tree master swagger learn 1 代码结构 2 代码 User packag
  • vue中一个项目里兼容移动端和pc端

    话不多说 上代码 先来看一下我的文件 路由文件 index js import Vue from vue import Router from vue router Vue use Router export default new Rou
  • 【实践经验】PPT导出SVG格式通过Inkscape转化为pdf

    目录 背景 方案调研 Inkspace 配置 将svg转为pdf 背景 在写论文过程中不可避免需要作图 常用的工具就是PPT 但是在导出图片的过程中通常会遇到一个问题 图片导出为png格式不够清晰 放大后比较模糊影响观感 那么有没有解决方案
  • AcWing4118. 狗和猫

    输入样例1 3 6 10 4 0 CCDCDD 4 1 2 0 CCCC 4 2 1 0 DCCD 输出样例1 Case 1 YES Case 2 YES Case 3 NO 样例1解释 在 Case 1 中 一共有 1010 份狗粮和 4
  • VTK环境安装教程

    安装前依赖环境 CMake VS2019 VTK压缩包 8 2 0即可 build过程 第一次分析完 找到下图中选中项 勾选Configure 解释勾选项 BUILD EXAMPLES 生成一些vtk官方的examples 帮助理解学习 当
  • SQL 后计算的利器 SPL

    目录 专业的结构化数据对象 强大的结构化数据计算能力 灵活的流程控制能力 优化体系结构 SPL资料 现代应用开发中 通常只用SQL实现简单的数据存取动作 而主要的计算过程和业务逻辑直接在应用程序中实现 主要原因在于 过于复杂的SQL很难调试