相关文章推荐
打酱油的手套  ·  python datetime ...·  2 年前    · 
谦逊的佛珠  ·  linux awk 加法-掘金·  2 年前    · 
帅气的煎饼果子  ·  Tkinter 2. ...·  2 年前    · 

上一篇的 sql 语句蛮简单的,接下来,来看一个相对复杂的的场景。假设我们要编写一个查询,计算期间物料进出存的查询。需要用到 5 个表,将创建表的 sql 语句贴在下面,示例数据也已经上传到 github。

物料主数据表 (material_numbers):

create table material_numbers (
    [MaterialNo] varchar(20) primary key,
    [Description_e] varchar(100) null,
    [Description_c] varchar(100) null

仓位 (storage_locations)

    create table storage_locations(
        [StorageLocation] varchar(10) PRIMARY KEY,
        [LocationType] varchar(10) NULL,
        [Description] varchar(50) NULL

movement_types:

CREATE TABLE movement_types(
	[MovementTypeID] varchar(10) PRIMARY KEY,
	[Description] varchar(50) NULL,
	[InOutSign] varchar(1) NULL

stock_movement_headers:

CREATE TABLE stock_movement_headers(
    [DocNo] varchar(10) PRIMARY KEY,
    [MovementType] varchar(10) NULL,
    [RefDocNo] varchar(10) NULL,
    [VendorID] varchar(10) NULL,
    [CustomerID] varchar(10) NULL,
    [DocDate] datetime NULL,
    [PeriodID] varchar(10) NULL,
    [GCInvoiceNo] varchar(15) NULL,
    [LongText] text NULL,
    [PostedBy] varchar(10) NULL,
    [PostedDate] datetime NULL,
    [Remarks] varchar(255) NULL

stock_movement_details:

CREATE TABLE stock_movement_details(
    [DocNo] varchar(10),
    [MaterialNo] varchar(20),
    [StorageLocation] varchar(10) NULL,
    [Qty] float NULL,
    [Remarks] varchar(255) NULL,
    PRIMARY KEY(DocNo, MaterialNo)

在 MS Access 中表主要字段及表之间的关系:

查询条件是计算出 2008 年 4 月份物料的进出存,筛选条件:

- MaterialNo: Like "B180*'
- StorageLocation: 1001

最终的数据显示格式如下:

第一步:构建物料清单

首先构建 material_numbers 和 storage_locations 的组合 (笛卡尔乘积)。考虑到有些物料没有交易数据,这种组合能得到交易项全部为 0 的数据。在查询设计界面中,加入 material_numbers 和 storage_locations 两个表,双击 MaterialNo 和 StorageLocation 字段,将其加入到查询的字段。两个表为独立的状态,这样查询的结果就是一种笛卡尔乘积。在【条件】中,MaterialNo 输入 “B180*”, StorageLocation 输入 “1001”:

选中 material_numbers 表,将右边【属性表】表的别名改为 M,同样的方法将 storage_locations 表的别名改为 L。设置别名的目的是让 SQL 语句变得清晰。如果【属性表】没有出现,选中表,右键菜单有【属性】项,点击调出。完成后的界面应该如下所示:


进入 SQL 视图,此时 SQL 语句如下。因为 Access 不支持代码格式化和高亮,代码借助 Visual Studio Code 进行格式化。

SELECT
    M.MaterialNo,
    L.StorageLocation
    material_numbers AS M,
    storage_locations AS L
WHERE
        ((M.MaterialNo) Like "B180*")
        AND ((L.StorageLocation) = "1001")

第二步:构建交易清单

新建一个查询,将查询命名为 txns。查询基于三个表:

- stock_movement_headers: 交易表头
- stock_movement_details : 交易行项目
- movement_types : 移动类型,表示出入库的类型

因为没有维护表之间的关系,需要在查询中维护 stock_movement_headers 表和 movement_types 表之间的关系(左连接):

双击或拖放的方式选中需要的字段到查询中:


为了方便后面的根据年月筛选,基于 DocDate 新增两个计算字段: TxYear 和 TxMonth,分别表示交易的年和月。在表达式生成器中维护:


增加一个计算列 ActualQty, 正数表示入库,负数表示出库:

ActualQty: IIf([InOutSign]="+",Nz([Qty]),-1 * Nz([Qty]))

为了 SQL 语句更加清晰,设置三个表的别名:

H:  stock_movement_headers
D:   stock_movement_details
MVT:  movement_types

然后对 materialNo 字段和 storageLocation 字段设置上一步相同的条件。设置完成后,查询设计视图的界面如下:

进入 SQL 视图,得到本步骤的 SQL 语句:

SELECT
    H.DocDate,
    D.MaterialNo,
    D.StorageLocation,
    H.MovementType,
    D.Qty,
    MVT.InOutSign,
    Year([DocDate]) AS TxYear,
    Month([DocDate]) AS TxMonth,
    IIf([InOutSign] = "+", Nz([Qty]), -1 * Nz([Qty])) AS ActualQty
        stock_movement_headers AS H
        LEFT JOIN movement_types AS MVT ON H.MovementType = MVT.MovementTypeID
    INNER JOIN stock_movement_details AS D ON H.DocNo = D.DocNo
WHERE
        ((D.MaterialNo) Like "B180*")
        AND ((D.StorageLocation) = "1001")

运行一下查询,此时的界面如下:

第三步:添加条件列

接下来基于查询 txns 创建一个查询,使用行转列的方法增加三个计算列:

- BeginQty: 期初余额
- StockIn: 期间入库数量
- StockOut: 期间出库数量

将查询命名为 txn_summary,首先选取相关的列:


添加条件列,在表达式生成器界面中设置 BeginQty 的公式如下:

BeginQty: IIf([TxYear]<2008 Or ([TxYear]=2008 And [TxMonth]<4),[ActualQty],0)

同样的方法,添加计算列,得到物料入库数量和出库数量:

StockIn: IIf([TxYear]=2008 And [TxMonth]=4 And [InOutSign]="+",[ActualQty],0)
StockOut: IIf([TxYear]=2008 And [TxMonth]=4 And [InOutSign]="-",[ActualQty],0)

删除查询中不相关的字段(TxYear, TxMonth, InoutSign, ActualQty),然后点击功能区上的汇总

将需要计算的字段改为合计


完成本步骤,得到的 SQL 语句为:

SELECT
    txns.MaterialNo,
    txns.




    
StorageLocation,
    Sum(
        IIf(
            [TxYear] < 2008
            Or (
                [TxYear] = 2008
                And [TxMonth] < 4
            [ActualQty],
    ) AS BeginQty,
    Sum(
        IIf(
            [TxYear] = 2008
            And [TxMonth] = 4
            And [InOutSign] = "+",
            [ActualQty],
    ) AS StockIn,
    Sum(
        IIf(
            [TxYear] = 2008
            And [TxMonth] = 4
            And [InOutSign] = "-",
            [ActualQty],
    ) AS StockOut
GROUP BY
    txns.MaterialNo,
    txns.StorageLocation;

因为本步骤基于查询 txns,所以可以将查询稍加修改,并且插入上一步骤 txns 查询的代码。From 子句原来是这样的:


将其修改为:

括号中插入上一步 txns SQL 语句的码, 将其作为子查询:

SELECT
    txns.MaterialNo,
    txns.StorageLocation,
    Sum(
        IIf(
            [TxYear] < 2008
            Or (
                [TxYear] = 2008
                And [TxMonth] < 4
            [ActualQty],
    ) AS BeginQty,
    Sum(
        IIf(
            [TxYear] = 2008
            And [TxMonth] = 4
            And [InOutSign] = "+",
            [ActualQty],
    ) AS StockIn,
    Sum(
        IIf(
            [TxYear] = 2008
            And [TxMonth] = 4
            And [InOutSign] = "-",
            [ActualQty],
    ) AS StockOut
        SELECT
            H.DocDate,
            D.MaterialNo,
            D.StorageLocation,
            H.MovementType,
            D.Qty,
            MVT.InOutSign,
            Year([DocDate]) AS TxYear,
            Month([DocDate]) AS TxMonth,
            IIf([InOutSign] = "+", Nz([Qty]), -1 * Nz([Qty])) AS ActualQty
                stock_movement_headers AS H
                LEFT JOIN movement_types AS MVT ON H.MovementType = MVT.MovementTypeID
            INNER JOIN stock_movement_details AS D ON H.DocNo = D.DocNo
        WHERE
                ((D.MaterialNo) Like "B180*")
                AND ((D.StorageLocation) = "1001")
    ) AS txns
GROUP BY
    txns.MaterialNo,
    txns.StorageLocation;

计算期末库存

联合查询 material (别名 MT) 和 txn_summary (别名 TX),创建一个新的查询:


此时的 SQL 语句为:

SELECT
    MT.MaterialNo,
    MT.StorageLocation,
    TX.BeginQty,
    TX.StockIn,
    TX.StockOut,
    [BeginQty] + [StockIn] + [StockOut] AS EndQty
    materials AS MT
    LEFT JOIN txn_summary AS TX ON (MT.StorageLocation = TX.StorageLocation)
    AND (MT.MaterialNo = TX.MaterialNo);

将 FROM 子句后 materialstxn_summary 替换为子查询,得到最后完整的 SQL 语句:

SELECT
    MT.MaterialNo,
    MT.StorageLocation,
    TX.BeginQty,
    TX.StockIn,
    TX.StockOut,
    [BeginQty] + [StockIn] + [StockOut] AS EndQty
        SELECT
            M.MaterialNo,
            L.StorageLocation
            material_numbers AS M,
            storage_locations AS L
        WHERE
                ((M.MaterialNo) Like "B180*")
                AND ((L.StorageLocation) = "1001")
    ) AS MT
    LEFT JOIN (
        SELECT
            txns.MaterialNo,
            txns.StorageLocation,
            Sum(
                IIf(
                    [TxYear] < 2008
                    Or (
                        [TxYear] = 2008
                        And [TxMonth] < 4
                    [ActualQty],
            ) AS BeginQty,
            Sum(
                IIf(
                    [TxYear] = 2008
                    And [TxMonth] = 4
                    And [InOutSign] = "+",
                    [ActualQty],
            ) AS StockIn,
            Sum(
                IIf(
                    [TxYear] = 2008
                    And [TxMonth] = 4
                    And [InOutSign] = "-",
                    [ActualQty],
            ) AS StockOut
                SELECT
                    H.DocDate,
                    D.MaterialNo,
                    D.StorageLocation,
                    H.MovementType,
                    D.Qty,
                    MVT.InOutSign,
                    Year([DocDate]) AS TxYear,
                    Month([DocDate]) AS TxMonth,
                    IIf([InOutSign] = "+", Nz([Qty]), -1 * Nz([Qty])) AS ActualQty
                        stock_movement_headers AS H
                        LEFT JOIN movement_types AS MVT ON H.MovementType = MVT.MovementTypeID
                    INNER JOIN stock_movement_details AS D ON H.DocNo = D.DocNo
                WHERE
                        ((D.MaterialNo) Like "B180*")
                        AND ((D.StorageLocation) = "1001")
            ) AS txns
        GROUP BY
            txns.MaterialNo,
            txns.StorageLocation
    ) AS TX ON (MT.StorageLocation = TX.StorageLocation)
    AND (MT.MaterialNo = TX.MaterialNo);

github: stocks.accdb

  《SQL Server 2008宝典》全面介绍了SQL Server 2008各方面的知识,全书由6部分组成:第1部分为数据库的基础篇,介绍了数据库的类型、概念、对象、SQL语言等;第2部分为SQLServer 2008的准备篇,介绍了SQL Server 2008的功能、特性、各版本的比较、安装方法、SQL Server 2008的服务、客户端的工具等;第3部分为SQL Server 2008的基本操作篇,介绍如何管理与配置SQL Server 2008服务、如何创建数据库和数据表、如何对数据库里的数据进行操作;第4部分为数据库管理篇,介绍如何使用T-SQL程序对数据进行复杂的运算,以及如何使用视图、存储过程、触发、索引、用户定义数据类型、用户定义函数、全文索引、游标、事务和锁、统计信息和同义词等方面的知识;第5部分为SQL Server高级技术,介绍如何进行数据库备份与恢复、如何规划数据库、如何保证数据库的安全、复制与发布、自动化管理、如何使用性能工具优化数据库、数据的导入导出、SQL Server邮件的使用、Analysis Services、Reporting Services、SQL Server与XML的应用,以及如何使用客户端和应用程序访问SQL Server;第6部分为SQL Server 2008改进篇,介绍了SQL Server 2008相对于之前版本进行了哪些方面的重大改进和优化,进一步帮助读者了解SQL Server 2008更多的独有特性。   《SQL Server 2008宝典》适合SQL Server 2008的初学者学习,也适合子数据库的管理人员和开发人员阅读和参考。   《SQL Server 2008宝典》:实例丰富,内容充实。书中针对每一个知识点列举了大量实例来说明该功能如何实现,全书共有超过500个精彩实例。   讲解通俗,步骤详细。通过通俗易懂的语言讲解SQL Server 2008的各个强大功能,并配以插图讲解和详细的步骤说明,帮助读者快速掌握实用技能。   由浅入深,难易穿插。《SQL Server 2008宝典》面向入门级和提高级两类读者,每个知识点都采用由浅入深的讲解方式,并穿插介绍重点和难点。   提供源码,方便学习。书中涉及到的T—SQL程序在网站上提供下载,打开相应SQL文件即可直接执行其中的代码。   SQL Server 2008是一个能用于大型联机事务处理、数据仓库和电子商务等方面应用的数据库平台,也是一个能用于数据集成、数据分析和报表解决方案的商业智能平台,为用户提供了强大、集成、便于使用的工具,使系统管理员与普通用户能更方便、更快捷地管理数据库或设计、开发应用程序。 封面 -33 封底 803 扉页 -32 版权 -31 前言 -30 目录 -26 第1部分 基础篇 1 第1章 认识数据库 2 1.1 数据库的类型 2 1.1.1 结构型数据库 2 1.1.2 网络型数据库 2 1.1.3 关系型数据库 2 1.1.4 面向对象型数据库 3 1.2 数据库的基本概念 3 1.2.1 数据 3 1.2.2 数据库 3 1.2.3 数据库管理系统 3 1.2.4 数据库系统 3 1.3 常见的数据库对象 3 1.3.1 表与记录 4 1.3.2 主键与外键 4 1.3.3 索引 4 1.3.4 约束 5 1.3.5 视图 5 1.3.6 关系图 5 1.3.7 默认值 5 1.3.8 规则 5 1.3.9 存储过程 6 1.3.10 触发 6 1.3.11 用户和角色 6 1.4 数据库管理系统的基本功能 6 1.4.1 定义数据 6 1.4.2 处理数据 6 1.4.3 保证数据安全 6 1.4.4 备份和恢复数据 6 1.5 SQL语言简介 6 1.5.1 SQL语言的历史 7 1.5.2 SQL语言的优点 7 1.5.3 SQL语言分   《SQL Server 2008宝典》全面介绍了SQL Server 2008各方面的知识,全书由6部分组成:第1部分为数据库的基础篇,介绍了数据库的类型、概念、对象、SQL语言等;第2部分为SQLServer 2008的准备篇,介绍了SQL Server 2008的功能、特性、各版本的比较、安装方法、SQL Server 2008的服务、客户端的工具等;第3部分为SQL Server 2008的基本操作篇,介绍如何管理与配置SQL Server 2008服务、如何创建数据库和数据表、如何对数据库里的数据进行操作;第4部分为数据库管理篇,介绍如何使用T-SQL程序对数据进行复杂的运算,以及如何使用视图、存储过程、触发、索引、用户定义数据类型、用户定义函数、全文索引、游标、事务和锁、统计信息和同义词等方面的知识;第5部分为SQL Server高级技术,介绍如何进行数据库备份与恢复、如何规划数据库、如何保证数据库的安全、复制与发布、自动化管理、如何使用性能工具优化数据库、数据的导入导出、SQL Server邮件的使用、Analysis Services、Reporting Services、SQL Server与XML的应用,以及如何使用客户端和应用程序访问SQL Server;第6部分为SQL Server 2008改进篇,介绍了SQL Server 2008相对于之前版本进行了哪些方面的重大改进和优化,进一步帮助读者了解SQL Server 2008更多的独有特性。   《SQL Server 2008宝典》适合SQL Server 2008的初学者学习,也适合子数据库的管理人员和开发人员阅读和参考。   《SQL Server 2008宝典》:实例丰富,内容充实。书中针对每一个知识点列举了大量实例来说明该功能如何实现,全书共有超过500个精彩实例。   讲解通俗,步骤详细。通过通俗易懂的语言讲解SQL Server 2008的各个强大功能,并配以插图讲解和详细的步骤说明,帮助读者快速掌握实用技能。   由浅入深,难易穿插。《SQL Server 2008宝典》面向入门级和提高级两类读者,每个知识点都采用由浅入深的讲解方式,并穿插介绍重点和难点。   提供源码,方便学习。书中涉及到的T—SQL程序在网站上提供下载,打开相应SQL文件即可直接执行其中的代码。   SQL Server 2008是一个能用于大型联机事务处理、数据仓库和电子商务等方面应用的数据库平台,也是一个能用于数据集成、数据分析和报表解决方案的商业智能平台,为用户提供了强大、集成、便于使用的工具,使系统管理员与普通用户能更方便、更快捷地管理数据库或设计、开发应用程序。 封面 -33 封底 803 扉页 -32 版权 -31 前言 -30 目录 -26 第1部分 基础篇 1 第1章 认识数据库 2 1.1 数据库的类型 2 1.1.1 结构型数据库 2 1.1.2 网络型数据库 2 1.1.3 关系型数据库 2 1.1.4 面向对象型数据库 3 1.2 数据库的基本概念 3 1.2.1 数据 3 1.2.2 数据库 3 1.2.3 数据库管理系统 3 1.2.4 数据库系统 3 1.3 常见的数据库对象 3 1.3.1 表与记录 4 1.3.2 主键与外键 4 1.3.3 索引 4 1.3.4 约束 5 1.3.5 视图 5 1.3.6 关系图 5 1.3.7 默认值 5 1.3.8 规则 5 1.3.9 存储过程 6 1.3.10 触发 6 1.3.11 用户和角色 6 1.4 数据库管理系统的基本功能 6 1.4.1 定义数据 6 1.4.2 处理数据 6 1.4.3 保证数据安全 6 1.4.4 备份和恢复数据 6 1.5 SQL语言简介 6 1.5.1 SQL语言的历史 7 1.5.2 SQL语言的优点 7 1.5.3 SQL语言分 在对access数据库进行数据查询的时候要注意,where后面的条件要加单引号:select * from 故障记录 where 故障现象代码='F001'多条件查询实现的代码如下:string sql = "select * from 故障记录 where"; if(textBox_machine.Text!="") sql += " 机编号=" + ... Office 家族中,平时使用 MS Acess 的人非常少,如果从工作效率的角度来说,掌握了 Access,很多时候岂止是事半功倍啊!下面就介绍一种基于 Access 查询轻松构造 SQL 语句的方法。因为本文面向把 MS Office 作为办公工具的用户,熟练编写 SQL 语句的请忽略。 假设我们有如下的员工工时记录表: 目标是按固定月份 (1~12 月)的格式统计员工的工时,格式如下... 2011-05-28 20:39:59转载自http://www.cnblogs.com/everyday/archive/2009/09/24/1573612.htmlACCESS里面的iff的用法就相当于SQL里面的case when end.       具体的用法如下:SQL server 支持的查询语句命令case when:结构如下:casewhen 条件1 then 结果1when 条件2 then 结果2……end在access中,不支持case when 结构,使用 iif 代替:结构如 很多初学Access的朋友都说sql 语句不会写,把它归纳为难点,不想写。其实不然,大家都知道sql查询中的作用非常非常的大,是不得放弃的模块。其实语法也是很简单,常用的就以下几种: 基本查询 SELECT column1,columns2,... FROM table_name 说明:把table_name 的特定栏位资料全部列出来 SELECT * FROM table_name <br>4、 提供了强大的QueryFilter类构造查询条件,使得实现数据查询不再需要编写复杂SQL语句; <br>5、 提供类似IBatisNet的Sql模板功能,为复杂查询统计提供较直观的开发模式; <br>6、 提供代码生成... <br>4、 提供了强大的QueryFilter类构造查询条件,使得实现数据查询不再需要编写复杂SQL语句; <br>5、 提供类似IBatisNet的Sql模板功能,为复杂查询统计提供较直观的开发模式; <br>6、 提供代码生成... 很多时候为了程序的可扩展性和准确性等我们会在数据库中把对应bool类型或string类型的字段设置为int型。但是在程序中显示的时候我们希望能显示用户友好的内容,这个时候我们就需要把查找到的结果转换成用户友好的结果。要达到这个目的有几种方法可行,可以在查询的时候直接按照要求判断输出,也可以在查询到结果后在程序中通过相应方法更改结果后显示。本文讨论第一种方法。 使用SQL Server数据库和使用 简单介绍一些谓词的使用和意义。 在代码中我们经常会使用一些条件语句来进行数据的查询和筛选,今天就初步讲一下常用的谓词查询。 谓词BETWEEN……AND 从字面意义上来讲就是在两者之间,所以使用BETWEEN……AND字句可以查找属性值在指定连续的范围内的元组。与之相对的是NOT BETWEEN…AND ,表示不在指定范围内的元组。 示例: select * fr...