请教数据库高手,在access2003里,用sql语句查询实现两表关联查询用count更新其中一表?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了请教数据库高手,在access2003里,用sql语句查询实现两表关联查询用count更新其中一表?相关的知识,希望对你有一定的参考价值。

见图,两个表分别是T1,T2

假定T1A列的取值范围只可能是T2的A列里的数据。且T2的A列的值是不重复的没有多余行。
现在想实现的是把T1里A列与T2的A列对应的记录数汇总到C列。
拿图中数据举例,结果应该是
1 a 3
2 b 2
3 c 1
我自己sql不太熟悉,加上access里面似乎难度增加了不少,一直在报错必须有可更新的查询之类。
我把mdb文件上传了,大家可以下载来测试。
http://pan.baidu.com/s/1dDnJuZB

ACCESS数据库是可以用两个表关联的结果来更新其中一列表的。但是由于ACCESS Jet引擎功能较弱,它只能用数据表中实际存在的列的值来更新其中一张表,对于计算得来的列的列值是无法用于更新的,哪怕是事前将有查询关语句保存为一个固定名称的查询也不成。

例如 

update T2 a,(select A,count(A) as cnt from T1 group by A) b 
set a.C=b.cnt where b.A=a.A;

或者将其中的子查询“select A,count(A) as cnt from T1 group by A” 保存为查询“Q1”


上述语句改写如下

update T2 a,Q1 b set a.C=b.cnt where b.A=a.A;

上述两句的语法都没问题,但是无法执行(报错必须有可更新的查询)


这么办?因为cnt列是计算得来的,Jet无法利用该列更新T2的字段C,那我们就利用一张中间表T3来绕过这个限制。


先运行生成表查询,将上述子查询结果保存为表“T3”

select A,count(A) as cnt into T3 from T1 group by A;

再运行下列更新即可实现楼主的需求

update T2 a,T3 b set a.C=b.cnt where b.A=a.A;


如果以后要经常运行该操作,请先运行一下面两个动作查询来更新之前T3表里已有的数据,以免旧有数据影响更新查询的正确性。

1.清空旧数据

delete from T3;

2.存入新的子查询结果

insert into T3 SELECT A,count(a) as cnt from T1 group by A;

3.执行更新查询,更新T2表的C列

update T2 a,T3 b set a.C=b.cnt where b.A=a.A;

 

确实有些麻烦,但是目前暂时还未能找到不借助中间T3表的SQL语句解决方案。


*******

其实更新T2表的C列有些多余,因为我们可以非常方便地用选择查询得到你要的列表

select a.id,a.A,Nz(b.cnt,0) as C from T2 a left join 
(select A,count(A) as cnt from T1 group by a) b 
on b.A=a.A;

一句选择查询就搞定了,实在是没必要去花大把的精力来维护这个C列!

追问

谢谢,你回答得很认真,我测试下再说。

追答

再提供一个非连接的办法(使用DCount函数)。此法最方便,但是请注意这也是效率最低的方案!其理由我就不说了。
update T2 set C=Nz(DCount("[A]","T1","[A]='" & [A] & "'") ,0)

参考技术A Select [T2].A,[T2].C from [T2] Left join Select * from (Select [T1].A, count(*) as 数量 from [T1] group by [T1].A) as [查询1] on [T2].A=[查询1].A;
如果你觉得写得累,可以用很简单的办法解决,直接把T1按A列统计一下,然后保存为查询1,再把查询1跟T2连接查询就可以了追问

你上面的代码报“From”子句错误。

参考技术B 感觉上应该是用merge语句,可是我不会用access,不知道他里面有没有merge语句,而且merge没有insert我也不知道行不行,你试试吧。不行就算了。
merge into T2
using (select A,count(*) B from T1 group by A) TT
on T2.A=TT.A
WHEN MATCHED THEN
UPDATE SET
T2.C=TT.B;追问

很遗憾没有,我也试过07版了。

参考技术C select id,t2a,count(*) as c from (

select t1.a as t1a,t2.id,t2.a as t2a from t1,t2 where t1.a=t2.a
)
c就是你需要的数据追问

你的语句复制出来语法都是错误,你上面是手打的根本没测试过。希望严谨一点好吗?

追答

怎么可能,你是完全复制的吧?你手敲一遍试试,我倒是觉得你不太适合做技术的。。。。

追问

我上面所有需要的资料都上传了,你如果测试过,肯定会把sql语句原封不动地复制到这里。如果你说你懒得下载、测试,我没什么好说的。

参考技术D 用程序分别链接sqlserver2008 和 ACCESS数据库
然后进行代码进行比较。追问

没有程序,只是纯数据库里执行sql。还有,最好用sql语句来回答问题,不需要多余的建议。

Delphi的高手请进,请教一个关于窗体创建的问题!

我在一个窗体放了大量的控件并且用了VCLSKIN,因此窗体在第一次SHOW的时候会出现一个从Delphi最原始的风格到所使用的皮肤的渐变的过程,不爽。因此我将窗体的宽高设为0再SHOW再Hide,再还原窗体大小,在SHOW。这个蠢办法是把问题解决了,可各位大侠可有什么更好的方法呢,希望不吝赐教啊!
我已经加入了 加载窗体
可是如何在加载窗体中 实现主窗体的show 而且还悄悄的进行

真没什么好办法可以解决,由于VCLSKIN没有提供源码,不知道它是在那一个事件后开始重画的。以前也没有大量的控件在窗口上,不过你也一说,倒也感觉到VCLSKIN是在窗口画好的情况下再来实现界面的,所以真不好解决。我也想了一个笨法子,不知道能不能达到你想要的效果。
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, SkinCaption, WinSkinStore, WinSkinData, SpTBXControls,
SpTBXItem, TntStdCtrls, StdCtrls, TntMenus, TBXDkPanels, Menus, TB2Item,
TBXSwitcher, TBX, TB2Dock, TB2Toolbar, ComCtrls, ToolWin, ExtCtrls,
Grids, Mask, Buttons;

type
TForm1 = class(TForm)
Memo1: TMemo;
Button1: TButton;
Label1: TLabel;
ListBox1: TListBox;
ComboBox1: TComboBox;
RadioGroup1: TRadioGroup;
SpeedButton1: TSpeedButton;
MaskEdit1: TMaskEdit;
StringGrid1: TStringGrid;
Image1: TImage;
ScrollBox1: TScrollBox;
ControlBar1: TControlBar;
StaticText1: TStaticText;
ColorBox1: TColorBox;
RichEdit1: TRichEdit;
ListView1: TListView;
ToolBar1: TToolBar;
StatusBar1: TStatusBar;
TBXDockablePanel1: TTBXDockablePanel;
TBXToolbar1: TTBXToolbar;
TBXMultiDock1: TTBXMultiDock;
TBXDock1: TTBXDock;
TBXSwitcher1: TTBXSwitcher;
TBPopupMenu1: TTBPopupMenu;
TBXButton1: TTBXButton;
TntGroupBox1: TTntGroupBox;
TntEdit1: TTntEdit;
TntPopupMenu1: TTntPopupMenu;
TntMemo1: TTntMemo;
TntCheckBox1: TTntCheckBox;
TntListBox1: TTntListBox;
SpTBXToolbar1: TSpTBXToolbar;
SpTBXSpeedButton1: TSpTBXSpeedButton;
SpTBXButton1: TSpTBXButton;
SkinData1: TSkinData;
SkinStore1: TSkinStore;
SkinCaption1: TSkinCaption;
procedure FormCreate(Sender: TObject);
procedure SkinData1AfterSkinForm(Sender: TObject; ahwnd: HWND;
aName: String);
private
Private declarations
public
Public declarations
end;

var
Form1: TForm1;

implementation

$R *.dfm

procedure TForm1.FormCreate(Sender: TObject);
begin
form1.AlphaBlend:=true;
form1.AlphaBlendValue:=0;

end;

procedure TForm1.SkinData1AfterSkinForm(Sender: TObject; ahwnd: HWND;
aName: String);
begin
form1.AlphaBlend:=false;
form1.AlphaBlendValue:=255;

end;

end.
参考技术A 君不见众软件打开的时候都喜欢一个欢迎界面?
加它的理由很简单
1.版权
2.美观
3.暗地里把事情忙完了(加载组件,皮肤等初始化参数)
参考技术B 嘿嘿,仔细考虑了下
你这个还是不错的方法
嘿嘿

以上是关于请教数据库高手,在access2003里,用sql语句查询实现两表关联查询用count更新其中一表?的主要内容,如果未能解决你的问题,请参考以下文章

请教oracle高手 在oracle里怎么样用一个插入语句插入两表里的数据

请教Access数据库文本转日期的方法

请教VB6.0 中DataGrid 操作Access数据库的问题

c# Winform 打印问题,请教高手

用access打开*.mdb数据库时,提示没有权限,让管理员设置适当的权限,有高手吗,我在线等

Delphi的高手请进,请教一个关于窗体创建的问题!