已是凌晨5点了,小弟还有一巨复杂的SQL问题没解决,哪位帮忙搞定它,多少分您说个数就是了。(200分)

  • 主题发起人 主题发起人 microwave
  • 开始时间 开始时间
M

microwave

Unregistered / Unconfirmed
GUEST, unregistred user!
小弟现有两个表:A,B。
A的结构为:
编号 日期1 日期2 品种 数量 顾员号
1 02-7-20 02-8-25 AA 2 5
2 02-7-19 02-8-29 BB 3 1
3 02-6-20 02-8-28 CC 1 2
4 02-8-1 02-8-18 BB 5 3
5 02-7-20 02-8-29 AA 6 2
6 02-7-20 02-8-29 CC 8 3
......


B的结构为:
日期 编号
02-8-20 1
02-8-20 3
02-8-20 5
02-7-26 1
02-7-26 5
02-6-28 3
......


我想由此两表得到第三个统计表C:
C的结构为:
顾员号 品种AA 品种BB 品种CC 小计
1 0 3 0 3
2 0 0 0 0
3 0 0 8 8
4 0 0 0 0
5 2 0 0 2
......

注:表C由表A中记录计算而得,且必须符合条件:
1. A中:日期1 >= X <= 日期2
2. B中:日期=X 的记录中要有A中符合条件的记录的 编号。
我列出的表C则是X=02-8-20的结果。

小弟用的是ADOquery连接ACCESS数据库。
不知如何写我才能得到此表C 请路过的诸位高人帮帮忙,事成之后,多少分,您开口就是了。
 
首先查询出符合条件的记录
,然后再使用交叉表来完成你的C表.//如果你的"品种"字段不是固定的话.
 
在Access中好象由一个Trans开头的函数可以完成Cross tab.如果不幸,可以使用TClientDataSet
作为临时表,首先查出所有记录然后遍历一片,构造临时表的结构(根据查得的品种,或者直接查品种的
基础表格也可以),然后循环,逐个填写即可。该方法我已经用过多次效果相当好。
 
TRANSFORM SUM(数量)
SELECT 顾员号,SUM(数量) as 小计
FROM A
WHERE (日期1<=#2002-08-20# and #2002-08-20#<=日期2)
AND
顾员号 in (select 编号 from B where 日期=#2002-08-20#)
GROUP BY 顾员号
PIVOT 品种

得到的是

顾员号 小计 AA BB CC
1 3 3
3 8 8
5 2 2

至于其它顾员号,再另行加入此表中
 
TRANSFORM SUM(数量)
SELECT 顾员号,SUM(数量) AS 小计 FROM
(SELECT 顾员号,品种,数量
FROM A
WHERE (日期1<=#2002-08-20# and #2002-08-20#<=日期2)
AND
顾员号 in (select 编号 from B where 日期=#2002-08-20#)
UNION
SELECT 顾员号,品种,0 as 数量 FROM A)
GROUP BY 顾员号
PIVOT 品种

也可这样,但也只会列出所有表A中所出现的顾员号,如顾员号不出现在表A中,则不会列出
 
我的意见是用外关联,和多个连机视图,或者是写多个视图,这样就可以用一个SQL
实现,而且,你的锚表选对了的话,也可以实现的
 
select a.顾员号,sum(iif(品种=‘aa',数量,0))as 品种AA,
sum(iif(品种=‘bb',数量,0))as 品种bb,
sum(iif(品种=‘cc',数量,0))as 品种cc,
sum(数量) //品种AA+品种bb+品种cc
from a left join b
on a.编号=b.编号 and b.日期>a.日期1 and b.日期<a.日期2
group by a.雇员号
order by a.雇员号


 
同意QuickSliver第一种说法,在得出结果表后,可以重新按顾客号排序即可得到你要的结果.
 
To:QuickSilver
您的第一种方法非常好,但还是有点问题:
此处:
顾员号 in (select 编号 from B where 日期=#2002-08-20#)
应为:
编号 in (select 编号 from B where 日期=#2002-08-20#)
还有,为什么我用此语句得不到数据,而改成:
编号 not in (select 编号 from B where 日期=#2002-08-20#)
却有数据,为什么?

 
根据你给出的表A和B的部分数据,我仔细看了看,如果你要满足条件2,那从表A中取出満足
条件的记录应为
SELECT * FROM A
WHERE (日期1<=#2002-08-20# and #2002-08-20#<=日期2)
AND 编号 in (select 编号 from B where 日期=#2002-08-20#)

编号 日期1 日期2 品种 数量 顾员号
1 02-7-20 02-8-25 AA 2 5
3 02-6-20 02-8-28 CC 1 2
5 02-7-20 02-8-29 AA 6 2

在这个表的基础上再进行数据交叉统计,是不可能得到你要的表C的结果
最终得到的是

顾员号 小计 AA CC
2 7 6 1
5 2 2

所以要得到表C的结果,应该是
顾员号 in (select 编号 from B where 日期=#2002-08-20#)
 
SORRY,是我自己的句子出了问题,已经能得到数据,是对的,是用:
编号 in (select 编号 from B where 日期=#2002-08-20#)
开始我得不到数据的原因是日期错了,很奇怪:为什么我用 datetostr(date) 得到的日期竟然是 1899-12-4 而用 floattostr(date)
得到的才是今天的日期 02-8-20 ???
 
To:QuickSilver
你的方法我采用了,但还有一点问题,生成的字段顺序是: 顾员号,小计 ,品种A,品种B……
我想要的顺序是:顾员号,品种A,品种B……,小计 不知可不可以?
 
在 select * 的 "*"的地方直接写你的字段名:

select 顾员号,品种A,品种B……,小计 ... From ....
 
SELECT * INTO TEMP FROM
(SELECT 顾员号,品种,数量
FROM A
WHERE (日期1<=#2002-08-20# and #2002-08-20#<=日期2)
AND 顾员号 in (select 编号 from B where 日期=#2002-08-20#)
UNION
SELECT 顾员号,"小计" as 品种,SUM(数量)
FROM (SELECT 顾员号,品种,数量
FROM A
WHERE (日期1<=#2002-08-20# and #2002-08-20#<=日期2)
AND 顾员号 in (select 编号 from B where 日期=#2002-08-20#))
GROUP BY 顾员号
)

先用上面这句生成临时表temp

再从临时表temp中得到最终结果

TRANSFORM SUM(数量)
SELECT 顾员号 FROM TEMP GROUP BY 顾员号
PIVOT 品种

顾员号 AA BB CC 小计
1 3 3
3 8 8
5 2 2

不过这样做太过繁琐,不建议这么做,此处只是给出一种实现方法而已
 
这样会不会影响效率?
 

Similar threads

D
回复
0
查看
2K
DelphiTeacher的专栏
D
D
回复
0
查看
1K
DelphiTeacher的专栏
D
D
回复
0
查看
1K
DelphiTeacher的专栏
D
I
回复
0
查看
891
import
I
S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
后退
顶部