posts - 8, comments - 0, trackbacks - 0, articles - 11

2012年9月12日

一程序员家的水管坏了,他打电话叫来一个水管工修理。 水管工鼓捣了一个小时,终于把管子修好了,他递给程序员一张600元的帐单。 “600元!”程序员愤怒地说:“我当程序员一天都赚不了这么多钱!” “是啊。”水管工平静地说,“我当程序员的时候也是。”

posted @ 2012-10-29 14:04 a_alter 阅读(520) | 评论 (0)编辑 收藏

例  如下
表  A 
(1--->n) 表B (B 可能为空)
(n---->n)表C
(n---->n)表D

现在有如下问题  在查询的时候我们允许b为空的A数据
Select * from A,B where A.B_AID = B.AID(+)

扩展查询  如果进行B关联C级别的条件过滤
Select * from A,B, C where A.B_AID = B.AID(+) and B.C_AID = C.AID;  

这个时候C能够知道B是可以为空的, 这个时候的join效果是, 如果在A关联B  B存在的情况下 在使用 C的join 条件进行筛选。 这个时候B为空的A条件还是可以摆查出来的。 只不过数据列B为空而已

再进行扩展筛选  进行C关联D级别的条筛选
Select * from A,B,C,D where A.B_AID = B.AID(+) and B.C_AID = C.AID and C.D_AID = D.AID;  

这样的D级别的筛选就会破坏B级别的赛选。
这个时候测试效果就是 D 级别的join条件 会破坏 B的left join 效果。

你可能想到改写条件如下
Select * from A,B,C,D where A.B_AID = B.AID(+) and B.C_AID = C.AID and C.D_AID(+) = D.AID;  

可惜我测试结果和full join 的效果是一样的,不是oracle高手, 谁知道的留个言火链接  谢谢

=======================================================================
后来找同学帮忙  得知他以前也遇到这情况
改写为如下条件
select * from (Select ....,C.D_AID from A,B,C where A.B_AID = B.AID(+) and B.C_AID = C.AID ) E,D where E.D_AID(+) = D.AID
这样就不会破坏B(+) 效果。  

个人理解就是 select 的组织数据效果。具体不清楚 欢迎发言。

=======================================================================
补充:
今天我才知道  left join 和 inner join 栏位是否必填还有关系。

在这个问题上有个地方被欺骗了 

就是在 A Left join B  inner JOIN C 的时候   如果 B 的 C 字段是必填的话  那么就相当于  left join。 如果不是必填的话 你必须手动的指示 left join (+)  。
=====================================================================
补充 2012/10/19   发现以上的理解不全面

A--B(+) 意思指B 端可为空, 如果 对B -- C 下面的元素进行赛选, 在局部看 B 和 C 的关系是两段都必须存在的, 但是在A -- B(+) 的前提下 C可以为空的,  所以需要使用 B --- C(+) 来进行关联  这样的坏处是可能会加载出 B  (存在)-- C (不存在) 这样的错误数据。 当然如果系统中有对这种数据有确实保障的时候可以忽略该问题

如果没有确切的保障的话
可能就需要使用 A --- D(+) 其中D 为  select * from B,C where B = C 这样的过滤方式, 但是这样就增加了复杂度, 你需要将可能用到的查询条件和查询结果集在D中 select 一一列出来

在 Select A.*,R1,R2,R3 from A ,(select B.A_Aid,c1,c2,c3,R1,R2,R3 from B,C where B.C_AID= C.Aid) D where A.Aid = B.A_Aid and c1 = ? and c2 = ? ....

Sql 复杂度高了一点。





posted @ 2012-10-09 10:15 a_alter 阅读(604) | 评论 (0)编辑 收藏

本文用途:因为暂时没有时间去具体看oracle sql的官方文档 ,纪录oracle的一些特殊写法。 (不断更新)
1. with ...  as ...
with querya as (select * from TB_Test)
2  case .. (when .. then) .... (when ..  then) .. else ... end
    SELECT FO_FULFILL_TRX_STRING.SEQUENCE_NO, AC_TYPE_ORDER.CODE, CASE
    WHEN AC_TYPE_ORDER.CODE = 'SO'
    THEN ( SELECT ORDER_NUMBER FROM SO_ORDER WHERE SO_ORDER.AID = FO_FULFILL_TRX_STRING.AID_ORDER_SO )
    ELSE ( SELECT ORDER_NUMBER FROM PO_ORDER WHERE PO_ORDER.AID = FO_FULFILL_TRX_STRING.AID_ORDER_PO )
    END ORDER_NUMBER
    FROM FO_FULFILL_TRX_STRING, AC_TYPE_ORDER.CODE
------------------------------------------------------------------------------------------------------------------------------
MYSQL 正则支持
select * from tb_rule_list where expression regexp '^.*\\$\\{0}\\[3].*$';
Oracle  正则函数支持
ORACLE中的支持正则表达式的函数主要有
    REGEXP_LIKE :与LIKE的功能相似
    REGEXP_INSTR :与INSTR的功能相似
    REGEXP_SUBSTR :与SUBSTR的功能相似
    REGEXP_REPLACE :与REPLACE的功能相
 
------------------------------------------------------------------------------------------------------------------------------
在MYSQL 中 select 可以显示 不是group by 中的分组字段, 可以是任意的数据列,具体数据显示的是分组后的第一行数据
在ORACLE中 select 是严格的 只能显示group by 中的字段。
同样效果的两行sql --- 让自己注意提高自己的使用灵活性
1. select a.aid AAid,nvl(b.cot,0) countline from po_draft_order a,(select AID_DRAFT_ORDER_PO BAID,count(*) cot from  po_draft_line group by AID_DRAFT_ORDER_PO) b WHERE A.AID = B.BAID(+);
2. select a.aid, (select count(*) from po_draft_line where AID_DRAFT_ORDER_PO = a.aid ) c from po_draft_order a;
-------------------------------------------------------------------------------------------------------------------------------
oracle 分级
rank()/dense_rank()  over(partition by ... order by ...)  加强对分组排序之后的数据的控制力。
over:  over(...)
partition by :  相当于group by
order by e.sal desc:  按工资从高到低排序(使用rank()/dense_rank() 时,必须要带order by否则非法)
rank()/dense_rank():  分级
整个语句的意思就是:在按部门划分的基础上,按工资从高到低对雇员进行分级,“级别”由从小到大的数字表示(最小值一定为1)。 
那么rank()和dense_rank()有什么区别呢?
rank():  跳跃排序,如果有两个第一级时,接下来就是第三级。
dense_rank():  连续排序,如果有两个第一级时,接下来仍然是第二级。
min()/max() over(partition by ...)  // 分组最大最小值
lead()/lag() over(partition by order by) // 前后数据比较使用
lead(列名,n,m):  当前记录后面第n行记录的<列名>的值,没有则默认值为m;如果不带参数n,m,则查找当前记录后面第一行的记录<列名>的值,没有则默认值为null。
lag(列名,n,m):  当前记录前面第n行记录的<列名>的值,没有则默认值为m;如果不带参数n,m,则查找当前记录前面第一行的记录<列名>的值,没有则默认值为null。
主要是各个函数和over的配合使用。
-----------------------------------------------------------------------------------------------------------------------------------------------------
Oracle 的集合运算
UNION 用来合并结果集 要求返回字段是一样的。
JOIN 用来合并字段。
并集
UNION ALL, FULL JOIN -- 重复出现
UNION, INNER JOIN minus -- 一次出现
交集
intersect
差集
minus 
笛卡尔积
CROSS JOIN
------------------------------------------------------------------------------------------------------------------------------
INNER JOIN oracle 特殊的写法 不知道在sqlserver 是否支持。
SELECT
*
FROM (
  SO_WEC_SODL_DESPATCH_HEADER AS SO_WEC_SODL_DESPATCH_HEADER_1
    INNER JOIN (
      (
        SO_WARRANTY_ENTITLEMENT WET_1
        INNER JOIN (SO_WARRANTY_ENTITLEMENT INNER JOIN SO_WEC_SODL
        ON SO_WARRANTY_ENTITLEMENT.AID = SO_WEC_SODL.AID_WARRANTY_ENTITLEMENT_SO
        ) ON (WET_1.AID_COMPANY = SO_WARRANTY_ENTITLEMENT.AID_COMPANY)
        AND (WET_1.SEQ_ITEM_NUM = SO_WARRANTY_ENTITLEMENT.PARENT_SEQ_ITEM)
        AND (WET_1.ITEM_LINE_NUM = SO_WARRANTY_ENTITLEMENT.PARENT_ITEM_NUM)
        AND (WET_1.SO_LINE_NUM = SO_WARRANTY_ENTITLEMENT.PARENT_SOLINE_NUM)
        AND (WET_1.SO_NUM = SO_WARRANTY_ENTITLEMENT.SO_NUM)
      )
      INNER JOIN SO_WEC_SODL AS SO_WEC_SODL_1 ON (SO_WEC_SODL.LINE_DELIVERY_NUMBER = SO_WEC_SODL_1.LINE_DELIVERY_NUMBER)
      AND (WET_1.AID = SO_WEC_SODL_1.AID_WARRANTY_ENTITLEMENT)
    ) ON SO_WEC_SODL_DESPATCH_HEADER_1.AID_WEC_SODL = SO_WEC_SODL_1.AID
) INNER JOIN SO_WEC_SODL_DESPATCH_HEADER ON SO_WEC_SODL.AID = SO_WEC_SODL_DESPATCH_HEADER.AID_WEC_SODL

===


posted @ 2012-09-12 12:57 a_alter 阅读(207) | 评论 (0)编辑 收藏