Sql ,贷记或借记的金额越多,期初余额就越多。让我们看看为什么会发生这种情况,删除分组和聚合,检查我们真正总结的内容: SELECT vn.type, vn.name, v.date, vn.obal, v.credit, v.debit ; FROM v, vn ; WHERE v.name = vn.name
输出:Sql ,贷记或借记的金额越多,期初余额就越多。让我们看看为什么会发生这种情况,删除分组和聚合,检查我们真正总结的内容: SELECT vn.type, vn.name, v.date, vn.obal, v.credit, v.debit ; FROM v, vn ; WHERE v.name = vn.name,sql,foxpro,visual-foxpro,Sql,Foxpro,Visual Foxpro,输出: TYPE NAME DATE OBAL CREDIT DEBIT bank abc 06/01/2012 100 0 50 bank abc 06/02/2012 100 0 60 bank abc 06/03/2012 100 0 70 bank def 06/01/2012 200 0 50 bank
TYPE NAME DATE OBAL CREDIT DEBIT
bank abc 06/01/2012 100 0 50
bank abc 06/02/2012 100 0 60
bank abc 06/03/2012 100 0 70
bank def 06/01/2012 200 0 50
bank def 06/02/2012 200 0 60
bank def 06/03/2012 200 0 70
bank ghi 06/01/2012 300 0 50
bank ghi 06/02/2012 300 0 60
ledger xyz 06/04/2012 400 0 50
ledger xyz 06/05/2012 400 0 60
ledger pqr 06/06/2012 500 0 50
ledger pqr 06/07/2012 500 0 60
ledger pqr 06/08/2012 500 0 70
你可以看到,比如说对于“abc”,OBal 100重复了3次,因为v中有3个条目。当它只有100的时候,加起来就是300
当您使用SUM()或AVG()之类的聚合时,应该先在没有连接的情况下进行聚合,然后再进行连接。您仍然可以使用联接进行聚合,只要联接结果是一对多的关系。如果上述结果集为:
TYPE NAME OBAL CREDIT DEBIT
bank abc 100 0 180
bank def 200 0 180
bank ghi 300 0 110
ledger xyz 400 0 110
ledger pqr 500 0 180
可以按类型(1对多的1边)求和()
话虽如此,添加VFP支持子查询让我们编写一个解决方案:
Local sd,ed
sd = Date(2012,6,1) && start date of transactions
ed = Date() && current date as the end date...
Select vn.Type, Sum(vn.OBal - tmp.TotCd) As Opbal, Sum(tmp.Curbal) As Curbal ;
FROM vn ;
LEFT Join ;
(Select v.Name, Sum(Iif(v.Date < sd, v.credit-v.debit, 0)) TotCd, ;
SUM(Iif(Between(v.Date, sd, ed), v.credit-v.debit, 0)) Curbal ;
FROM v ;
GROUP By v.Name ) tmp On tmp.Name = vn.Name ;
GROUP By vn.Type ;
ORDER By vn.Type ;
HAVING Sum(vn.OBal - tmp.TotCd + tmp.Curbal) != 0
您需要在
vn
表中按分组,然后将该结果加入到您的查询中。@Dems:我在想按vn分组需要什么。键入查询。有了按类型分组的obal,我认为你的答案很好。(顺便问一下,在Foxpro中,这个在ORDER By
之后是否有有效语法?这让我很好奇)我假设vn
的主键是name
,根据描述。@ypercube-我的错,主键是name
,而不是type
。我想我刚刚看到了name
我应该看到的type
@ypercube:我已经很久没有使用FoxPro了,我也没有使用过FoxPro for Windows或Visual FoxPro,但是DOS版本在SELECT语句中的子句顺序方面有一定程度的自由度,也许该产品的后续版本保留了这种放纵的样本。设置,抱歉!它会产生一条错误消息:“函数名丢失”。“不幸的是,6年前的这个问题被推到了头版:(原因是这个问题急需一些解释,而设计也存在缺陷。不知道这些细节,就没有好的答案。1)永远不要依赖旧引擎行为来解决此错误。这是一个错误,已更正。依靠一个bug不是一个好办法。2) 要创建日期值,千万不要通过从字符串转换来创建。这取决于设置。最好使用solid date()、datetime()函数或严格的date\datetime文本。
SET ENGINEBEHAVIOR 90
CREATE CURSOR vn;
( date d, ;
name c(25), ;
type c(25), ;
obal n(7) )
INSERT INTO vn VALUES ( CTOD( "5/20/2012" ), "person 1", "person type 1", 125 )
INSERT INTO vn VALUES ( CTOD( "5/20/2012" ), "person 2", "another type ", 2155 )
CREATE CURSOR v;
( date d, ;
name c(25), ;
desc c(50), ;
debit n(7), ;
credit n(7))
INSERT INTO V VALUES ( CTOD( "6/1/2012" ), "person 1", "description 1", 10, 32 )
INSERT INTO V VALUES ( CTOD( "6/2/2012" ), "person 1", "desc 2", 235, 123 )
INSERT INTO V VALUES ( CTOD( "6/3/2012" ), "person 1", "desc 3", 22, 4 )
INSERT INTO V VALUES ( CTOD( "6/4/2012" ), "person 1", "desc 4", 53, 36 )
INSERT INTO V VALUES ( CTOD( "6/5/2012" ), "person 1", "desc 5", 31, 3 )
INSERT INTO V VALUES ( CTOD( "6/1/2012" ), "person 2", "another 1", 43, 664 )
INSERT INTO V VALUES ( CTOD( "6/4/2012" ), "person 2", "more desc", 78, 332 )
INSERT INTO V VALUES ( CTOD( "6/6/2012" ), "person 2", "anything", 366, 854 )
sd = CTOD( "6/3/2012" ) && start date of transactions
ed = DATE() && current date as the end date...
select;
vn.name,;
vn.type,;
MAX( vn.obal ) as BalByNameOnly,;
SUM( IIF( v.date < sd, v.credit-v.debit, 000000.00 )) OpBal, ;
SUM( IIF( BETWEEN(v.date, sd, ed), v.credit - v.debit, 000000.00 )) CurBal ;
FROM ;
v,;
vn ;
WHERE ;
v.name = vn.name;
GROUP BY ;
vn.Name,;
vn.Type;
INTO ;
CURSOR C_JustByName READWRITE
Name Type BalByNameOnly OpBal CurBal
person 1 person type 1 125 -90 -63
person 2 another type 2155 621 742
SELECT ;
JBN.type, ;
JBN.BalByNameOnly - JBN.OpBal as OpBal,;
JBN.CurBal ;
FROM ;
C_JustByName JBN ;
GROUP BY ;
vn.type ;
ORDER BY ;
vn.type ;
HAVING ;
OpBal + CurBal != 0;
INTO ;
CURSOR C_Final
SELECT vn.type, SUM(vn.obal + IIF(v.date < sd, v.credit-v.debit, 0)) OpBal, ;
SUM(IIF(BETWEEN(v.date, sd, ed), v.credit-v.debit, 0)) CurBal ;
FROM v, vn WHERE v.name = vn.name GROUP BY vn.type ;
ORDER BY vn.type HAVING OpBal + CurBal != 0
CREATE CURSOR vn ( date d, name c(25), type c(25), obal n(7) )
INSERT INTO vn (date, name, type, obal) VALUES ( DATE(2012,5,20), "abc", "bank", 100 )
INSERT INTO vn (date, name, type, obal) VALUES ( DATE(2012,5,20), "def", "bank", 200 )
INSERT INTO vn (date, name, type, obal) VALUES ( DATE(2012,5,20), "ghi", "bank", 300 )
INSERT INTO vn (date, name, type, obal) VALUES ( DATE(2012,5,20), "xyz", "ledger", 400 )
INSERT INTO vn (date, name, type, obal) VALUES ( DATE(2012,5,20), "pqr", "ledger", 500 )
CREATE CURSOR v ( date d, name c(25), desc c(50), debit n(7), credit n(7))
INSERT INTO V (date,name,desc,debit,credit) VALUES ( DATE(2012,6,1), "abc", "description 1", 50, 0 )
INSERT INTO V (date,name,desc,debit,credit) VALUES ( DATE(2012,6,2), "abc", "description 1", 60, 0 )
INSERT INTO V (date,name,desc,debit,credit) VALUES ( DATE(2012,6,3), "abc", "description 1", 70, 0 )
INSERT INTO V (date,name,desc,debit,credit) VALUES ( DATE(2012,6,1), "def", "description 1", 50, 0 )
INSERT INTO V (date,name,desc,debit,credit) VALUES ( DATE(2012,6,2), "def", "description 1", 60, 0 )
INSERT INTO V (date,name,desc,debit,credit) VALUES ( DATE(2012,6,3), "def", "description 1", 70, 0 )
INSERT INTO V (date,name,desc,debit,credit) VALUES ( DATE(2012,6,1), "ghi", "description 1", 50, 0 )
INSERT INTO V (date,name,desc,debit,credit) VALUES ( DATE(2012,6,2), "ghi", "description 1", 60, 0 )
INSERT INTO V (date,name,desc,debit,credit) VALUES ( DATE(2012,6,4), "xyz", "description 1", 50, 0 )
INSERT INTO V (date,name,desc,debit,credit) VALUES ( DATE(2012,6,5), "xyz", "description 1", 60, 0 )
INSERT INTO V (date,name,desc,debit,credit) VALUES ( DATE(2012,6,6), "pqr", "description 1", 50, 0 )
INSERT INTO V (date,name,desc,debit,credit) VALUES ( DATE(2012,6,7), "pqr", "description 1", 60, 0 )
INSERT INTO V (date,name,desc,debit,credit) VALUES ( DATE(2012,6,8), "pqr", "description 1", 70, 0 )
SELECT vn.type, SUM(vn.obal + IIF(v.date < sd, v.credit-v.debit, 0)) OpBal, ;
SUM(IIF(BETWEEN(v.date, sd, ed), v.credit-v.debit, 0)) CurBal ;
FROM v, vn WHERE v.name = vn.name GROUP BY vn.type ;
ORDER BY vn.type HAVING OpBal + CurBal != 0
TYPE OPBAL CURBAL
------- ----- ------
bank 1500 -470
ledger 2300 -290
SELECT vn.type, vn.name, v.date, vn.obal, v.credit, v.debit ;
FROM v, vn ;
WHERE v.name = vn.name
TYPE NAME DATE OBAL CREDIT DEBIT
bank abc 06/01/2012 100 0 50
bank abc 06/02/2012 100 0 60
bank abc 06/03/2012 100 0 70
bank def 06/01/2012 200 0 50
bank def 06/02/2012 200 0 60
bank def 06/03/2012 200 0 70
bank ghi 06/01/2012 300 0 50
bank ghi 06/02/2012 300 0 60
ledger xyz 06/04/2012 400 0 50
ledger xyz 06/05/2012 400 0 60
ledger pqr 06/06/2012 500 0 50
ledger pqr 06/07/2012 500 0 60
ledger pqr 06/08/2012 500 0 70
TYPE NAME OBAL CREDIT DEBIT
bank abc 100 0 180
bank def 200 0 180
bank ghi 300 0 110
ledger xyz 400 0 110
ledger pqr 500 0 180
Local sd,ed
sd = Date(2012,6,1) && start date of transactions
ed = Date() && current date as the end date...
Select vn.Type, Sum(vn.OBal - tmp.TotCd) As Opbal, Sum(tmp.Curbal) As Curbal ;
FROM vn ;
LEFT Join ;
(Select v.Name, Sum(Iif(v.Date < sd, v.credit-v.debit, 0)) TotCd, ;
SUM(Iif(Between(v.Date, sd, ed), v.credit-v.debit, 0)) Curbal ;
FROM v ;
GROUP By v.Name ) tmp On tmp.Name = vn.Name ;
GROUP By vn.Type ;
ORDER By vn.Type ;
HAVING Sum(vn.OBal - tmp.TotCd + tmp.Curbal) != 0
TYPE OPBAL CURBAL
------- ----- ------
bank 600 -470
ledger 900 -290