壹佰网|ERP100 - 企业信息化知识门户

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 1245|回复: 14

救命呀,有个SQL实在想不出怎么写来,请各路大侠踊跃出手。

[复制链接]
发表于 2008/12/8 09:07:09 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。如果您注册时有任何问题请联系客服QQ: 83569622  。

您需要 登录 才可以下载或查看,没有帐号?注册

x
救命呀,有个SQL实在想不出怎么写来,请各路大侠踊跃出手。

系统中有A、B两个表,A表和B表是多对多关系,关联条件为A.A1=B.B1 and A.A2=B.B2,但是A表或B表中任何一条记录只要与对方匹配成功1次,那么这条记录就不在参加以后的运算比如
A表中记录为 A1       A2
                    2         4
                    2         4
                    1         2
                    1         2
                    3         5
B表的记录为 B1       B2
                    2         4
                    2         4
                    2         4
                    1         2
                    2         7
如果SQL为 select A1,A2,B1,B2 from A,B
where A.A1=B.B1 and A.A2=B.B2
得到的结果为 A1      A2      B1      B2
                    2        4        2        4
                    2        4        2        4
                    2        4        2        4
                    2        4        2        4
                    2        4        2        4
                    2        4        2        4
                    1        2        1        2
                    1        2        1        2

而我希望得到是:
                     2        4        2        4
                     2        4        2        4
                     1        2        1        2
想了一星期也没想出怎么写来,请各位大侠支招呀
发表于 2008/12/8 09:30:55 | 显示全部楼层
照你的说法,结果应该是
                     2        4        2        4
                     1        2        1        2
啊!
如果得出的是你要的那种结果,我是不是可以理解为首先我找出所有符合条件的,即A.A1=B.B1 and A.A2=B.B2的数据。统计出max(count(*)),然后减一就好啦。

比如你举的这个例子:首先A.A1=B.B1 and A.A2=B.B2的数据,在A表中有
                    2         4
                    2         4
                    1         2
                    1         2
B表中有          2         4
                    2         4
                    2         4
                    1         2
统计出最大个数max(count(*))分别为(2,4)的是3,(1,2)的是2,减一后为2,1,即结果为
                     2        4        2        4
                     2        4        2        4
                     1        2        1        2
发表于 2008/12/8 10:02:31 | 显示全部楼层
如果是这样的话,语法可以写成这样:第一步
(select   DISTINCT A1,A2,B1,B2 from A,B
where A.A1=B.B1 and A.A2=B.B2)C
求出关联数据
(select A.A1,A.A2,count(A.A1,A.A2) as s
from A,C
where  A.A1=C.C1 and  A.A2=C.C2
GROUP BY  A.A1,A.A2) D
求出A表中的count(*)
同样求出B表中的count(*)  (E)

并起来:
(select  * from D
union
select  * from E) F

然后我们求出每组的最大数并减一:
select F.A1,F.A2,(max(s)-1) as n
from F
group by  F.A1,F.A2
到这基本上就清楚了。
先去工作了,等会有时间再来完善下。
发表于 2008/12/8 10:41:38 | 显示全部楼层
再加两个条件:
1.去除B表中的重复数据

2.去除A表中A.A1='1'的重复数据
发表于 2008/12/8 11:09:37 | 显示全部楼层
本帖最后由 molwang 于 2008-12-8 11:17 编辑

SELECT A1,A2,(MAX(s)-1) AS n
FROM
(select A.A1,A.A2,count(*) as s
from A,(select   DISTINCT A1,A2,B1,B2 from A,B
where A.A1=B.B1 and A.A2=B.B2)C
where  A.A1=C.A1 and  A.A2=C.A2
GROUP BY  A.A1,A.A2
UNION  (ALL)
select B.B1,B.B2,count(*) as s
from B,(select   DISTINCT A1,A2,B1,B2 from A,B
where A.A1=B.B1 and A.A2=B.B2)C
where  B.B1=C.A1 and  B.B2=C.A2
GROUP BY  B.B1,B.B2) D
GROUP BY A1,A2

得出结果:
A1            A2            n
1                 2                 1
2                 4                 2
下面就是怎么转换为
A1     A2
1        2
2        4
2        4
暂时还没想到有什么好方法,谁补充下。
发表于 2008/12/8 11:15:15 | 显示全部楼层
本帖最后由 molwang 于 2008-12-8 11:16 编辑

假设已经转换完成,语法定为SQL
则最终语法可以写为
SELECT E.A1 AS A1,E.A2 AS A2,F.A1 AS B1, F.A2 AS B2
FROM
(SELECT A1,A2,(MAX(s)-1) AS n
FROM
(select A.A1,A.A2,count(*) as s
from A,(select   DISTINCT A1,A2,B1,B2 from A,B
where A.A1=B.B1 and A.A2=B.B2)C
where  A.A1=C.A1 and  A.A2=C.A2
GROUP BY  A.A1,A.A2
UNION (ALL)
select B.B1,B.B2,count(*) as s
from B,(select   DISTINCT A1,A2,B1,B2 from A,B
where A.A1=B.B1 and A.A2=B.B2)C
where  B.B1=C.A1 and  B.B2=C.A2
GROUP BY  B.B1,B.B2) D  GROUP BY A1,A2) E,(SQL) F
where E.A1 = F.A1 AND E.A2 = F.A2
发表于 2008/12/8 13:05:00 | 显示全部楼层
实在不行我这还有个麻烦点的:
第一步:
SELECT H.A1,H.A2,H.N
into c
FROM
(select H.A1,H.A2 ,H.N
FROM (SELECT A1,A2,MAX(N)AS M
FROM
(SELECT A.A1,A.A2,L.N
FROM
(SELECT A1,A2,COUNT(*) AS N FROM A
GROUP BY A1,A2)L,A
WHERE A.A1=L.A1 AND A.A2=L.A2
UNION ALL
SELECT B.B1,B.B2,L.N
FROM
(SELECT B1,B2,COUNT(*) AS N FROM B
GROUP BY B1,B2)L,B
WHERE B.B1=L.B1 AND B.B2=L.B2)H
GROUP BY A1,A2)K,(SELECT A.A1,A.A2,L.N
FROM
(SELECT A1,A2,COUNT(*) AS N FROM A
GROUP BY A1,A2)L,A
WHERE A.A1=L.A1 AND A.A2=L.A2
UNION ALL
SELECT B.B1,B.B2,L.N
FROM
(SELECT B1,B2,COUNT(*) AS N FROM B
GROUP BY B1,B2)L,B
WHERE B.B1=L.B1 AND B.B2=L.B2)H
WHERE H.A1=K.A1 AND H.A2=K.A2 AND H.N= K.M)H
,(select distinct A1,A2 from A,B
where A.A1=B.B1 and A.A2=B.B2) J
WHERE H.A1=J.A1 AND H.A2=J.A2
将需要的数据插入到表C(可以用临时表,我闲麻烦,先建了个表)
第二步:ALTER TABLE c ADD id int IDENTITY (1, 1)
增加标识列,方便取数。
第三步:SELECT A1,A2,A1,A2
FROM
(SELECT distinct C.A1,C.A2,C.ID
FROM C,(SELECT A1,A2,MAX(ID)AS ID from c
GROUP BY A1,A2)D
WHERE C.ID NOT IN (SELECT ID FROM (SELECT A1,A2,MAX(ID)AS ID from c
GROUP BY A1,A2)D))Y
显示效果变成想要的那种。
 楼主| 发表于 2008/12/8 13:37:50 | 显示全部楼层
其实我的终极目标是达到这样的效果:
                 A1      A2      B1      B2
                         2        4        2        4
                         2        4        2        4
                         Null    Null     2       4
                         1        2        1        2
                         1        2        Null    Null
                         3        5        Null    Null
                         Null    Null     2        7
当然A表和B表除了A1,A2,B1,B2都还有其他的列。
发表于 2008/12/8 14:55:55 | 显示全部楼层
那我再帮你看看吧,应该可以的
发表于 2008/12/8 15:07:37 | 显示全部楼层
本帖最后由 molwang 于 2008-12-8 15:44 编辑

这个更简单
使用A、B表单据号id(或者是其他类似字段),然后下面语法就可以了
select a.a1,a.a2,b.b1,b.b2  from a  FULL JOIN b on a.a1=b.b1 and a.a2=b.b2 and a.id = b.id
这个前提是A、B表中能对应上的数据的单据号要一样
举例说下A表中有2个(2,4),其单据号分别为IDA1、IDA2
           B表中有3个(2,4),其单据号分别为IDB1、IDB2、IDB3
则要求IDB1、IDB2、IDB3 包含 IDA1、IDA2
如果不是这样,那就复杂了。
发表于 2008/12/8 15:15:03 | 显示全部楼层
select a.a1,a.a2,a.b1,a.b2
from (
select distinct a.rowid,'a' s,a.a1,a.a2,b.b1,b.b2,c.n
from   a,b,
(
select a1,a2,count(*)  n
from a
group by a1,a2
) c
where  a.a1=b.b1
and    a.a2=b.b2
and    a.a1=c.a1
and    a.a2=c.a2
union all

select distinct b.rowid ,'b' s,a1,a2,b.b1,b.b2,c.n
from   a,b,
(
select b1,b2,count(*)  n
from b
group by b1,b2
) c
where  a.a1=b.b1
and    a.a2=b.b2
and    c.b1=b.b1
and    c.b2=b.b2
) a,

(
select sum (a1) a1,sum(a2) a2
       ,least(sum(an),sum(bn)) n,decode(sign(sum(an)-sum(bn)),
                                   -1,'a',0,'a',1,'b','') sig
from                                                                                 
(
SELECT a.a1||a.a2 a,A.A1,A.A2,COUNT(*) aN,0 b1,0 b2,0 bn
FROM   A
GROUP BY A.A1,A.A2
UNION  
SELECT b.b1||b.b2 a,0,0,0,B.B1,B.B2,COUNT(*) N
FROM   B
GROUP BY B.B1,B.B2
)
group by a
having least(sum(an),sum(bn))<>0
) h
where a.s=h.sig
and   a.n=h.n
and   h.a1=a.a1
and   h.a2=a.a2
order by a.a1
 楼主| 发表于 2008/12/9 08:28:39 | 显示全部楼层
一个牛人给了标准答案:
select a1,a2,b1,b2
from
(select a1,a2,a1||a2||ROW_NUMBER() over (partition by a1||a2 order by a1||a2 ) sna from a ) x,
(select b1,b2,b1||b2||ROW_NUMBER() over (partition by b1||b2 order by b1||b2 ) snb from b ) y
where x.sna=y.snb(+)
union all
select a1,a2,b1,b2
from
(select a1,a2,a1||a2||ROW_NUMBER() over (partition by a1||a2 order by a1||a2 ) sna from a ) x,
(select b1,b2,b1||b2||ROW_NUMBER() over (partition by b1||b2 order by b1||b2 ) snb from b ) y
where x.sna(+)=y.snb
and  x.sna is null
发表于 2008/12/9 13:59:33 | 显示全部楼层
呵呵。PL/SQL。的确强。
我只会T-SQL,接触ORCALE时间不长,PL/SQL还比较菜。
发表于 2008/12/10 12:52:16 | 显示全部楼层
写个函数更简单。
发表于 2008/12/15 13:19:23 | 显示全部楼层
本帖最后由 man417022791 于 2008-12-15 13:21 编辑

是不是你的表本身就有问题???
您需要登录后才可以回帖 登录 | 注册

本版积分规则

QQ|Archiver|小黑屋|手机版|壹佰网 ERP100 ( 京ICP备19053597号-2 )

Copyright © 2005-2012 北京海之大网络技术有限责任公司 服务器托管由互联互通
手机:13911575376
网站技术点击发送消息给对方83569622   广告&合作 点击发送消息给对方27675401   点击发送消息给对方634043306   咨询及人才点击发送消息给对方138011526

GMT+8, 2025/11/29 06:52 , Processed in 0.018936 second(s), 16 queries , File On.

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

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