ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 效率神器,一键搞定繁琐工作
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
让更多数据处理,一键完成 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
查看: 2369|回复: 10

[求助] 求助sql语句

[复制链接]

TA的精华主题

TA的得分主题

发表于 2013-5-13 04:17 | 显示全部楼层 |阅读模式
本帖最后由 startx 于 2013-5-13 04:22 编辑

我在Access 2010有两个表,Source,Removal。Removal是Source的子表,它们的3个Field字段完全相同。Removal的每一个Field字段都是Source的每一个feild的子集。
现在想生成第三个表Destination,需要用Source减去Removal后的数据。也就是如果Source的任何一条记录中的三个Field都在Removal中找到一样的记录,就不放入Destination,反之则放入。
我试图用下面这句sql来完成:
Select Source.*
Into Destination
From Source Left Outer Join Removal On (Source.a=Removal.a And Source.b=Removal.b And Source.c=Removal.c)
结果记录生成不正确。
Source有20639条记录,Removal有271条记录,按理说生成的新表记录应该是两者之差20368条记录,可是生成的表格记录却有20648条记录,记录数竟然增加了。显然有错误。
请高手相助!
有点线索,似乎Access 2010不支持Outer Join,如果不支持,寻解决方案。

TA的精华主题

TA的得分主题

发表于 2013-5-13 08:51 | 显示全部楼层
LEFT JOIN不是求差集的,是左连接,会返回左边的所有记录行数。

如果说有增加,说明on条件 的结果不是唯一的,是有重复的。也就是存在一对多的情况

ACCESS是支持OUTER JOIN的,你用的LEFT JOIN就是OUT JOIN的一种。

TA的精华主题

TA的得分主题

发表于 2013-5-13 10:02 | 显示全部楼层
你这个需求,似乎用NOT EXISTS会比较好。

TA的精华主题

TA的得分主题

 楼主| 发表于 2013-5-14 02:42 | 显示全部楼层
谢谢楼上两位。
2楼的说法是正确的。3楼的说法应该是正确的,但是耗时太多,几乎感觉死机,这是因为两表相乘的原因。
我尝试改写成如下语句:
Select Source.*
Into Destination
From Source Inner Join Removal On (Source.a & Source.b & Source.c <>Removal.a & Removal.b & Removal.c)
结果生成记录太多。把<>换成=,结果正确,和Removal表格完全一样。有些糊涂了。

TA的精华主题

TA的得分主题

 楼主| 发表于 2013-5-14 07:55 | 显示全部楼层
有朋友上飞机前在机场给我写了如下sql语句:
SELECT Source .*
FROM Source LEFT JOIN Removal ON (Source.a & Source.b & Source.c = Removal.a & Removal.b & Removal.c)
WHERE (((Removal.a & Removal.b & Removal.c) Is Null));
运行速度很快。不过我对条件语句不太懂。不是不懂这个条件是什么意思,而是不懂为什么这里要加这样一句。
另外,这个语句生成20377条记录。而Source有20639条记录,Removal有271条记录,按理说生成的新表记录应该是两者之差20368条记录。所以多出来9条记录。
写这语句的人是高手,我不大怀疑这条语句的正确性。所以向大家请教。

TA的精华主题

TA的得分主题

发表于 2013-5-14 10:45 | 显示全部楼层
startx 发表于 2013-5-14 07:55
有朋友上飞机前在机场给我写了如下sql语句:
SELECT Source .*
FROM Source LEFT JOIN Removal ON (Sourc ...

其实你朋友这个SQL这样写,你就会更明白一些了。
  1. SELECT Source .*, Removal.*
  2. FROM Source
  3. LEFT JOIN Removal ON (Source.a & Source.b & Source.c = Removal.a & Removal.b & Removal.c)
  4. WHERE (((Removal.a & Removal.b & Removal.c) Is Null))
复制代码

TA的精华主题

TA的得分主题

发表于 2013-5-14 11:00 | 显示全部楼层
按理用NOT EXISTS的效率要比做字符串拼合对比的效率要高,我把SQL写给你,你再试试看。
  1. SELECT *
  2. FROM Source
  3. WHERE NOT EXISTS
  4.      ( SELECT a,b,c
  5.             FROM Removal
  6.                 WHERE Source.a=Removal.a AND Source.b=Removal.b AND Source.c=Removal.c)
复制代码

评分

1

查看全部评分

TA的精华主题

TA的得分主题

 楼主| 发表于 2013-5-14 11:31 | 显示全部楼层
非常,非常,非常感谢老水牛的耐心回复!!!{:soso_e163:}

第六楼的回复,我没有看懂。貌似一样,不过格式有些不同,是么?你是演示给我看sql语句的书写规范吗?WHERE (((Removal.a & Removal.b & Removal.c) Is Null))有什么用呢?我还是糊涂中。

第七楼的回复,让我无比感动。为什么Not Exists效率比字符串合并的效率要高呢?我在哪里可以看到相关的资料?我尝试按照你写的SQL,查询结果显示第一页,但当我点击最后一条记录时死机。这个方法好像我试过,如果没记错的话,死机是常态。

TA的精华主题

TA的得分主题

发表于 2013-5-14 12:06 | 显示全部楼层
startx 发表于 2013-5-14 11:31
非常,非常,非常感谢老水牛的耐心回复!!!

第六楼的回复,我没有看懂。貌似一样,不过格 ...

我改写的那条SQL,在SELECT的时候,把Removal表中的字段也加进去了,这就是为什么你朋友在HWERE条件中,加上了那条IS NULL的作用。因为是LEFT JOIN ,所以在查询时REMOVAL表会有与Source表不匹配的记录。

评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2013-5-14 12:50 | 显示全部楼层
我的SQL是在SQL SERVER上写的,比对的字段要比你的多,有七个字段需要比对,查询生成1晚多条记录只需要0.1秒。不知道是不是ACCESS的效率相应要低一些,所以会产生死机的状态。

评分

1

查看全部评分

您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-12-31 05:27 , Processed in 1.038305 second(s), 21 queries , Gzip On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表