集算器序表和SQL数据表都是有结构的二维数据对象,都有记录、索引、主键的概念,都可以应用于结构化数据的计算。虽然都可以应用于结构化数据的计算,但两者的应用场景却有明显的区别,序表适合解决较复杂但数据量不是很大的计算问题,而数据表适合进行常规但可能数据量巨大的计算。
两者的不同是由底层机制决定的。
序表具有有序的特点,每条记录、每列数据都有确定的序号;序表支持显式集合,序表之间可以直接进行集合运算;序表也是泛型集合,其基本元素既可以是数值也可以是引用或者另一个集合。
SQL数据表缺乏上述特点,但它对内外存透明,可以用一致的语法来访问内存、外存或混合数据。
下面,我们将深入讨论两者的共同点和区别。
相同的基本功能
集算器序表和SQL数据表都是有结构的二维数据对象,即以记录为基础,多条记录形成行式的二维表,二维表配合列名形成完整的数据结构。因为结构上大体相似,所以两者的基本用法区别不大。
例1:查询对象中的数据。找到Freight大于100,并且是2013年以前的订单。
SQL:SELECT * FROM Orders WHERE Freight > 100 AND OrderDate < ’1998-01-01′
序表:= Orders.select(Freight > 100 && OrderDate < date(“1998-01-01″))
注:本例使用的数据对象名为订单(Orders),后面还会用到客户(Customers)。
例2:排序。将订单按EmployeeID正序排序,再按Freight逆序排序。
SQL:SELECT * FROM Orders ORDER BY EmployeeID ,Freight DESC
序表:=Orders.sort(EmployeeID,Freight:-1)
例3:分组汇总。按员工汇总,对运货费求和,对订单计数。
SQL:SELECT EmployeeID, COUNT(OrderID), SUM(Freight) FROM Orders GROUP BY EmployeeID
序表:= Orders.groups(EmployeeID;sum(Freight),count(OrderID))
例4:连接。将订单和客户这两个数据对象连接成新的数据对象,使用左连接,连接字段为CustomerID。
SQL:Select * from Orders left join Customers on Orders.CustomerID =Customers.CustomerID
序表:=join@1(Orders:, CustomerID; Customers:, CustomerID)
除了上述几种基本用法,集算器序表和SQL数据表在唯一值、计数、求和、平均、最大、最小值等算法上也非常相似,这里不再一一举例。
有序性的区别
序表的记录集合是有序的,因此可以轻松解决和顺序有关的计算。SQL数据表缺乏序号及序号相关的访问方法,这使它在序运算上不够方便。
例1:针对sales数据对象,计算每个月的销售额比上个月增长了百分之几。
SQL:
select salesAmount, salesMonth,
(case when
prev_price !=0 then ((salesAmount)/prev_price)-1
else 0
end) compValue
from (select salesMonth, salesAmount,
lag(salesAmount,1,0) over(order by salesMonth) prev_price
from sales) t
序表:
sales.derive(salesAmount / salesAmount [-1]-1: compValue)
比较:
每个月的销售额和序无关,在序表和数据表中的表示方法一样,都是salesAmount。和序有关的是:上个月的销售额,即相对于当前记录的上一条记录中的salesAmount。序表有序,可以用salesAmount[-1]来直接表示上个月的销售额。SQL数据表无序,在SQL2003标准后添加了窗口函数补充了一些序运算功能,但仍然比较繁琐,需要用lag(salesAmount,1,0) over(order by salesMonth)这种复杂的方法来计算出上个月的销售额。
序表还可以轻松表达相对区间,比如相对于当前月份的前两个月及后两个月共五个月的销售额,序表可以这样表达:salesAmount{-2,2}。在SQL中使用窗口函数也可以表达区间的汇总运算,但要麻烦得多。
例2:针对sales数据表,找出每种产品里销售额最高的前10条的记录。
SQL:
select salesMan, product ,amount
from ( select salesMan, product ,amount, rank() over (partition by product order by amount desc ) ranking from sales)
where ranking <=10
序表:
= sales.group(product).(~.top(-amount;10))
比较:
实现本例最直观的思路是将数据按产品分组,然后再进行分组内的序运算,简单的方法是直接取组内amount最小的前十条记录,直观的方法是按照amount对组内数据逆序排序,再取组内序号是1到10的记录。
序表对序运算支持良好,可以用top函数实现第一种算法(如例子中),也可以用sort函数和记录序号实现第二种算法,即:=sales.group(product).(~.sort(Amount:-1)).(~([to(10)]))。
SQL数据表记录没有次序,必须先计算出一个序号或者可代替序号功能的字段,比如排名。上述例子的算法就是先计算出组内数据的排名,再取排名前十的记录。显而易见,SQL算法有点曲折,语法也难懂,要用到复杂的窗口函数over (partition by…… order by……),以及难以跟踪调试的子查询。
相比之下,序表更加直接简便,也容易跟踪调试。比如程序员可以先写出=sales.group(product)这句代码进行测试,这句代码表示将数据分组,它可以独立运行并独立显示结果。如果分组结果符合预期,程序员可以继续加入第二段代码:对组内数据逆序排序,即.(~.sort(Amount:-1)),这里的“.”表示把前面的计算结果作为一个整体继续加工,“~”表示当前的组内数据,“-1”表示逆序。现在的代码是=sales.group(product).(~.sort(Amount:-1)),它仍然可独立运行并独立显示结果。观察或调试后,程序员可以加入第三段代码:取组内序号是1到10的记录,即.(~([to(10)]))。
可以看到,序表的计算过程可以步步递进,在解决复杂的计算问题时简化计算防止出错。事实上,上述连续的三段代码可以写成逐步引用的三行代码,这可以更加清晰地分解计算目标:
值得注意的是,SQL无法对数据先分组再执行有序计算,即使用临时表也无法实现,它必须将这两步合二为一,产生这一现象的原因是数据表不支持显式集合和泛型集合,语法表达能力较弱。
另外,SQL使用的窗口函数虽然是ansi标准,但数据库厂商并未完全按标准实现,不同的数据库里写法也会不同,有些数据库根本不提供窗口函数。而序表的函数语法独立于数据源,不论哪种数据源(包括数据库、Txt文件、Excel文件、二进制文件等),使用序表计算时都无需修改代码。
显式集合的区别
SQL有集合的概念,但不提供显式的集合,不能作为独立的变量存在,只能借助临时表来实现集合运算。而序表是真正的显式集合,可以实现集合运算。
例子:针对Contract数据对象进行计算,假设业务上将订购数量大于40的合同称为大合同,单价大于2000的合同称为重要合同,请找出既是大合同又是重要合同的当年合同,以及除此之外的其他合同。
SQL:
select SellDate,Quantity,Amount,Client from Contract where to_char(SellDate,’yyyy’)=’2014′ and quantity>=40 and AMOUNT>=2000
select SellDate,Quantity,Amount,Client from Contract where not(to_char(SellDate,’yyyy’)=’2014′ and quantity>=40 and AMOUNT>=2000)
序表:
=thisYear= Contract.select(year(SellDate)=2014)
=big= Contract.select(Quantity>40)
=importance = Contract.select(AMOUNT>2000)
=answer=thieYear^big^ importance
=others= Contract\answer
比较分析:
既是大合同又是重要的当年合同,这是比较典型的自然思考方式,使用交集运算最为直观。如果将大合同定义为big,重要合同定义为importance,当年的合同定义为thisYear,那我们可以很容易写出伪代码:big∩importance∩thiYear。序表是显式集合,可以很直观地表达等价的算法,即:thieYear^big^ importance。SQL不能用集合变量来表示,因此只能寻求其他方式,比如转换为布尔条件来表示,即例子中的: to_char(SellDate,’yyyy’)=’2014′ and quantity>=40 and AMOUNT>=2000。
第一问比较简单,因此两者的开发难度并没有太大的区别。随着问题的深入,两者的区别才会明显起来。
第二问:“除此之外的其他合同”,这也是典型自然思考方式,使用差集可以一步算出。序表的算法是:Contract\answer,非常直观。使用布尔条件,SQL也可以计算出答案,但表达式的写法和业务描述相差甚远,即:not(to_char(SellDate,’yyyy’)=’2014′ and quantity>=40 and AMOUNT>=2000)。
SQL也可以用集合运算来解答,算法也很直观,但是因为数据表不能用集合变量来表示,代码会显得非常冗长:
(select SellDate,Quantity,Amount,Client from Contract)
minus
(Select select SellDate,Quantity,Amount,Client from Contract from(
(select SellDate,Quantity,Amount,Client from Contract where to_char(SellDate,’yyyy’)=’2012′)
Intersect
(select SellDate,Quantity,Amount,Client from Contract where quantity>=40)
Intersect
(select SellDate,Quantity,Amount,Client from Contract where AMOUNT>=2000))
因为代码太冗长,所以很多人宁可使用布尔条件来间接实现集合运算。
当然,很多情况下数据表使用集合运算会比布尔条件更加方便,比如多个物理表之间的集合运算,或多层子查询之间的集合运算。这种情况下,将集合运算转化为布尔条件的代价就太高了,程序员必须接受冗长的集合运算。
泛型集合的区别
序表是泛型集合,除了存储实体数据,还可以存储指向关联数据的引用,这就使序表可以通过直观的对象引用实现关联计算。数据表只能存储实体数据,需要用复杂的关联语句才能完成等价的计算。
例子:
请计算获得总裁奖的部门经理们,其下属的年度优秀员工们都有谁。这里涉及两个数据对象:department和employee,其中,department的deptName字段和employee的empDept是一对一的关系,department中的manager字段和employee中的empName也是一对一的关系。另外,总裁奖的代码是PA;年度优秀员工的代码是EOY。
SQL:
SELECT A.*
FROM employee A,department B,employee C
WHERE A.empDept=B.deptName AND B.manager=C.empName AND A.empHonor=‘EOY’ AND C.empHornor=‘PA’
序表:
employee.select(empHonor: “EOY”,empDept.manager.empHornor:”PA”)
比较分析:
SQL的解法无疑是正确的,但其中的关联语句比较复杂,普通程序员理解费力。序表的解法比较直观,empHonor:”EOY”是条件之一:“年度优秀员工们都有谁”,而empDept.manager.empHornor表示员工的“所属部门.该部门的经理.该经理的获奖情况”,显然,这个值为PA就符合题目中的条件二:“获得总裁奖的部门经理们”。这就是对象引用。
对象引用允许程序员使用“.”操作符来引用相关数据,这可以将业务中的关联关系直观地翻译为计算机语言,可以方便地表达多层关系,可以直观地进行关联计算。
对内外存透明的区别
SQL
SQL数据表因为不支持泛型和集合数据,内存中的数据写到外存时不会丢失信息,因而具有对内外存运算的透明性。首次访问数据表时,数据通常来自外存;之后再访问同样的数据表时,数据就可以来自内存缓存;对于数据量较大的数据表,其一部分数据来自外存,而另一部分会来自于内存。无论数据是来自于内存还是外存,无论数据量是大还是小,数据表的访问语法并无区别,程序员无需为此书写不同的SQL语句。
序表
序表支持了泛型(特别是引用)和集合数据,内存中的数据写到外存时会丢失信息,不能再读入,这导致其运算无法对内外存透明。序表是纯内存数据对象,所能计算的数据量受到内存限制,不能太大;如果数据量较大,那就应当使用游标(集算器的另一种数据对象)来进行外存计算,而游标和序表的语法是不同的;如果想提高性能或进行业务逻辑复杂的计算,程序员还必须将数据在游标和序表之间进行转换。
比较
序表对内外存不透明,程序员需要书写不同的代码来适应内存、外存或混合计算,还需要为将来数据量的增长而修改代码,因此前期设计和后期维护的工作量较大。而SQL数据表对内外存透明,程序员只需书写一套代码就能适应不同规模的数据,设计和维护的工作量较小。
通过上述比较分析我们可以看出:数据有序、显示集合、泛型集合,序表的这些特点使它可以轻松解决和顺序有关的复杂问题,可以简化集合运算的复杂度,可以用直观的对象引用来处理复杂的多表关联。而SQL数据表对内外存透明,代码通用性更好。
相关推荐
标题中的“全球大洲国家地区SQL数据表含中英文名称以及地区代码和关联ID”指出,这个资源是一个SQL数据表,包含了全球所有大洲、国家和地区的相关信息。这些信息不仅有中文名称,也有英文名称,这表明数据表设计时...
SQL数据生成器是一种工具,主要用于在数据库环境中快速创建和填充大量的测试或示例数据。它对于软件开发、性能测试、数据库设计验证等场景非常有用。通过使用这种工具,用户可以自定义数据规则,生成符合特定业务...
在书中的例题和习题中,你会接触到如何使用SQL语句进行数据操作,包括SELECT语句用于查询,INSERT语句用于插入新数据,UPDATE语句用于修改现有数据,以及DELETE语句用于删除不需要的数据。 表是数据库中的核心组成...
### SQL实现两张无关联表的数据列合并在一张结果集中 #### 实现思路及技术要点解析 在实际工作中,我们经常会遇到需要将两张无关联表的数据列合并到一个结果集中的需求。这种操作可以帮助我们更好地组织数据,使得...
一个大规模复杂跨域语义解析和 text-to-SQL 数据集 Spider。该数据集由 11 名耶鲁大学学生标注,包含 10181 个问题和 5693 个独特的复杂 SQL 查询、200 个具备多个表的数据库,覆盖 138 个不同领域。
全国四级地区(省市县)数据表sql
MySQL 中国省市区SQL表数据
查询sql数据库每张表包含的数据条数 sql server 数据库 表 数据量
省市区管理sql数据表设计、以及全国省市区全部最新数据,省市区管理sql数据表设计、以及全国省市区全部最新数据,省市区管理sql数据表设计、以及全国省市区全部最新数据,
总结,将SQL表中的数据导出到Word文档涉及数据库连接、SQL查询、数据处理和文档生成等多个步骤。掌握这些技能有助于提高工作效率,尤其是在需要定期生成报告或分析数据时。通过使用适当的编程语言和库,可以自动化这...
SQL Compare(SQL数据对比工具)
最近由于应急,需要把sqlserver表和表数据在oracle中复制一份。表结构的创建比较简单,但是表的数据量太大,一时也想不到怎么把sqlserver表数据复制到oracle中,于是请教公司主管,用存储过程实现可以查询出所有数据...
关联表数据集SQL查询
标签“全世界国家地区名称SQL数据”再次重申了主题,意味着数据集的核心内容是全球各国和地区的名称,可能还涵盖了其他相关细节。 压缩包子文件的文件名称为“全世界国家数据库数据”,这表明压缩包内包含了一个或...
全国地区四级数据库cn_region_info.sql
标题中的“所有SQL数据集”指的是一个集合,包含了与SQL(结构化查询语言)相关的各种数据和示例,这是数据库管理和软件开发中的基础工具。SQL是用于管理关系数据库的标准编程语言,包括创建、更新、查询和操作数据...
本文将介绍三种批量插入数据的方法。第一种方法是使用循环语句逐个将数据项插入到数据库中;第二种方法使用的是SqlBulkCopy,使... 此例子为控制台输出程序,有两个类,一个为BulkData类,主要实现了表值参数和sqlbulk
这个压缩包文件包含了执行SQL语句和数据库表结构,使得用户能够快速构建一个完整的全国城市级别的数据源。 首先,数据库表结构是数据存储的基础。在SQL中,表是一种组织数据的方式,它由行和列组成,每一行代表一条...
"SQL Server表数据导出成Insert语句的工具"是一个专门为此目的设计的应用程序,它能帮助数据库管理员和开发人员高效地生成插入语句,以便在其他数据库中重建同样的数据结构和内容。 1. **数据导出的需求**:在不同...