最近在写几个关于“Project - Subitem - Task”的管理系统,说是系统还是有点夸大了,基本就是一个多表查询调用和insert、update的数据库操作,只是出现不少计算和统计的问题,使得SQL显得复杂。所以,有必要在一个阶段任务完成后,做一次总结,把一些测试过程中的SQL代码做总结,以防以后用到又忘记了,也欢迎各位DB码农一起吐槽。
这几个月陆续写了几个系统,最后一个系统是信用卡管理系统,也是SQL累积到较复杂的阶段,以这个为例子来整理这段时间以来的基于ACCESS和ASP的SQL多个表查询与计算统计代码是比较合适的。
vc+24KOsz6PN+9PDvc+6w7XEt72wuM2zvMbQxdPDv6jVy7WloaK27rbIoaK7ub/utci1yNDFz6KjrLb409ayu8/rwPvTw8jnobA1MdDF08O/qLncwO2hsdauwOC1xMjtvP6jrMjDyMu80rvxyKHO0rXEssbO8dDFz6KjrNfuusO+zcrH19S8usWquPbK/b7dv+LAtL3ivvajrLfFtb3X1Ly6tcTUxtb3u/q78tDpxOK3/s7xxvfJz8ilo6zK1rv60rLKx9K70fm3w87KtcSho9XiysfX9tXiuPa88rWlz7XNs7XE1K3S8qOsuty24Mr9vt2yorK7ysfSu7PJtvi+zbXEo6y2+MrH1NrTw7XEuf2zzNbQsru2z8ztvNPQ6NKqzbO8xrW9tcTQxc+itvi4xL34tPrC66GjPC9wPgoKPHA+vajBotK7uPZDcmVkaXRDYXJktcTK/b7dv+KjrM7SssnTw7XEysdBQ0NFU1MyMDA3o6zAqdW5w/thY2NkYqGj19y5sr2owaLI/bj2se2jrLfWsfDKx2NyZWRpdKOo0MXTw7+o0MXPoqOpoaJCaWxso6jVy7Wlo6mholBheW1lbnSjqLu5v+6jqaOsvqHBv9LU1+67+bShtcTK/b7dwrzI66OsvPXJ2cjf0+CjrLj8tuC1xLzGy+O6zc2zvMbQtNTaQVNQyc+hozwvcD4KCjxwPtX9yOfJz8PmtcRDcmVkaXRDYXJkIEluZm9ybWF0aW9utcTSs8Pmo6y/tL+0U1FMtcTT777ko7o8L3A+CjxwPjwvcD4KPHByZSBjbGFzcz0="brush:sql;">select Credit.ID as 序号, Credit.CCno as 索引, Credit.Bank as 银行, Credit.brand as 品牌, Credit.Card as 卡号, Format(Credit.limit,'Currency') as 额度, Credit.Belong as 持卡人, Credit.billday as 账单日, Credit.consumeday as 消费日, Count(Bill.CCno) as 账单数, Format(Credit.templimit,'Currency') as 临时额度, Format(Credit.unsettled,'Currency') as 未出账单金额, Format((Credit.limit+Credit.templimit-Credit.unsettled),'Currency') as 剩余额度, Credit.newtime as 更新时间 FROM Credit LEFT JOIN Bill ON Credit.CCno = Bill.CCno GROUP BY Credit.ID, Credit.CCno, Credit.Bank, Credit.brand, Credit.Card, Credit.limit, Credit.Belong, Credit.billday, Credit.consumeday, Credit.templimit, Credit.unsettled, Credit.newtime order by Credit.ID
Select语句中在as之后的名称可作为字段(列)的名;对于现实金额计数法和货币符号,则是用Format(字段或表达式,'Currency')得到¥12345.67格式;SQL中是可以用表达式的,如”额度+临时额度-未出账单金额“可以得到剩余额度等。由于用到Count(统计)Bill表中的对应银行的账单数量,所以用到了两个表的链接,即【Credit】和【Bill】两个表。两个表链接还是比较容易的,采用LEFT、INNER、RIGHT都可以实现Count,但其他用法需求里,这三个表链接方式是有区别的,特别在三张表以上的链接的应用就很重要了。

PS:隐去索引、银行、卡号等。
Bill Payment是三个表的同时调用,目的是一览无余地看到信用卡的账单、还款时间、还款情况等方面的信息,且看SQL语句:
select Bill.ID as 序号, Bill.CCno as 索引, Credit.bank as 银行, Credit.Card as 卡号,
Bill.BLno as 账单编号, Month(Bill.billdate) as 账单月份, Bill.paydate as 最后还款日期,
Format(Bill.balance,'Currency') as 本期账单金额, Max(Payment.Paydate) as 还款时间,
IIf(Max(Payment.Paydate) Is Not Null,IIf(Bill.balance-SUM(Payment.balance)<=0,'结清账单','部分还款,余'&Bill.paydate-date()&'天'),IIF(Bill.paydate-date()>0,Bill.paydate-date()&'天','逾期:'&date()-Bill.paydate&'天')) as 剩余还款时间,
Format(SUM(Payment.balance),'Currency') as 还款总金额,
Format(IIf(Bill.balance-SUM(Payment.balance)<=0,0,Bill.balance-SUM(Payment.balance)),'Currency') as 未还款金额,
IIf(Bill.balance-SUM(Payment.balance)<=0,'√','') as 账单完成
FROM (Credit INNER JOIN Bill ON Credit.CCno = Bill.CCno)
LEFT JOIN Payment ON Bill.BLno = Payment.BLno
GROUP BY Bill.ID, Bill.CCno, Credit.bank, Credit.Card, Bill.BLno,
Bill.billdate, Bill.paydate, Bill.balance
HAVING(Year(Bill.billdate)='2014' AND Month(Bill.billdate)='12')
order by Bill.ID Desc
Select语句中有Month(时间类型字段)来获取月份,也就有year(时间类型字段)、week()等获取相关时间信息;用Max、Min来获取一个字段(列)中最大或最小的数值,这个数值可以是数字或时间类型。
这段Select语句中涉及到了一个if语句,句式:IIF(字段或表达式,表达式为真的结果,表达式为假的结果),表达式可以再嵌套表达式。对上面”剩余还款时间“这个字段的if语句进行解析。
IIf(Max(Payment.Paydate) Is Not Null,IIf(Bill.balance-SUM(Payment.balance)<=0,'结清账单','部分还款,余'&Bill.paydate-date()&'天'),IIF(Bill.paydate-date()>0,Bill.paydate-date()&'天','逾期:'&date()-Bill.paydate&'天'))as 剩余还款时间
第一个if层(红色),IIf(Max(Payment.Paydate) Is Not Null,表达式为真的结果,表达式为假的结果),当【Payment】表中的Paydate(这里指还款时间)不是空值的时候(蓝色),也就是这时有【Bill】表中的某月的账单,但这个账单在表【Payment】有值(不是空值),那么执行”表达式为真的结果“;