目錄
1.K3客戶編碼對應關係…………………………………………4
2.船務系統發票……………………………………………….6
3.紗廠系統發票/CNS…………………………………………23
4.船務系統取消單………………………………………………36
5.紗廠系統取消單………………………………………………39
6.dn……………………………………………………………..43
7.Cdn……………………………………………………………51
8.剔除無效數據……………………………………………….53.
9.Invoice_summary………………………………………………54.
10.Invoice_summary2…………………………………………….56
11.hk2py………………………………………………………….58
12.對比兩部份數據……………………………………………59.
13.數據更新:new…………………………………………….62
14.數據更新:updated………………………………………….63
15.數據更新:deleted…………………………………………65
16.修改導入狀態:IMPORT_STATUS…………………………66
17.paytype……………………………………………………….68
18.emp…………………………………………………………72
19.從K3導入客戶資料…………………………………………75
20.從k3導入供應商資料…………………………………….81
21.Invoice_merge_sum…………………………………………82
22.Py2hk_deleted_sum……………………………………….84
23.Py2hk_new_sum…………………………………………….84
24.ar_xls………………………………………………………84
25.ar_xls_2……………………………………………………87
26.ar_invoice_out……………………………………………….88
为了理解方便,现在我参照AR中的图形,通过仔细写下分析过程,并不再截图的方式来发现规律,记录细节!随时间用的越多,我就越发现,开始觉得复杂的事物,通过慢慢的观察,静静的思考,然后我会找出各个部分之间的联系,开始时,我现在,不写以前了解到的那些总体上的轮廓,因为,我需要有更深的认识,更细更深的记录!
为了分析方便,现在我仅仅通过语言的方式,来把我对图形的理解一点一点,慢慢的,记录下来,希望,我通过这些分析之后,我不但,对这里面的每一个细节有全面的理解,也希望,在此之后,会在自己的工作之后,在脑海中留下,这每一个细节的记忆,我相信,这一轮之后,我不仅会记住,这个财务监督系统,到底获取了那些部门的数据,这些数据都存放在了那些数据库中,在大量的数据中,系统又需要了谁,而最后淘汰了谁,所以我会记住,这里面最终需要的会是那些表,那些字段,我也会记住,这些字段在这过程中,经过了怎样的名字变换和取值变换,而我也要进一步熟练操作这些,要达到相同的目标,我相信,我一定有更好的方法,在设计世界里,有个设计原则叫“高耦合,低内聚”,这样如果应需求,要修改的时候,这样可以涉及到的表,涉及到的数据库最少,修改也更加方便,因为里面的内容相互之间独立性能好,就如修改某一个字段的时候,以至于懂数据库的人就会修改,我也相信,一定有更好的方法来实现这个目标,我相信,经过这一轮,我有方法可以让系统运行得更快,因为涉及的中间表越少的时候,不但分析更加的简洁,修改更加的简洁,运行涉及的连接也大大减少,这样,在完成同样工作量的情况下,走最直接的路,而这种种最后,节省了运行时间和操作成本!
我要知道,在此之前,也得先熟悉这些环境,我知道,它这过程里,从分别以K3_HK,2.3,ds_erp为连接名的AIS20040902164905, AIS20041216164951,kamhing,ds_erp这四个数据库中选取了数据,所以这四个数据库是数据来源,是这一切分析的对象,我也要知道,有一个以2.252为连接名的dw2005数据库,这是系统运行过程中存放那些临时数据的地方,这里面有几个我们创建的新表,这几个表名千万要记住,因为等下我追着整个工作流程跑的时候,我不会因为不认识路而迷茫,接而迷失方向,还有一个以AR为连接名的AR 数据库,它存放最终的数据,这里也有新建的表,这个我相信自己肯定不会忘记,因为它在大家寄给我的邮件中,不止一次的见过,这表将前面的所有的数据库里面所有表里面所有值得获取的字段都存放到了自己的怀里,所以,当我需要我想要的内容的时候,我可以直接在这个最终的表中查找,这样比在前面那四个数据库中查找那些我们不知道字段存放在何处的数据,要来的方便的多!
现在,我要一边看着AR,一边分析,记录看到的,没看到的!
- 1. 我现在开始看第一个transform,
打开它,我看到这里只涉及两个enrtry,一个为tableinput,一个为tableoutput,我们打开tableinput,看到SQL编辑框,里面内容如下
Select substring(t.fnumber, 1,1)+substring(t.fnumber, 4,1)+ substring(t.fnumber, 6,4) as abbr, t.fnumber
from AIS20040902164905.dbo.t_organization t
left join AIS20040902164905.dbo.t_settle o
on t.FsetID=o.FitemID
left join AIS20040902164905.dbo.t_submessage v
on t.FRegionID=v.FInterID
union Select
substring(t2.fnumber, 3,2)+ substring(t2.fnumber, 6,4) as abbr, t2.fnumber from AIS20041216164951.dbo.t_organization t2
left join AIS20041216164951.dbo.t_settle o2
on t2.FsetID=o2.FitemID
left join AIS20041216164951.dbo.t_submessage v2
on t2.FRegionID=v2.FInterID
看到,substring,它是一个函数,顾名思义,是取字符串类型的某一部分的意思,如substring(t.fnumber, 1,1),就是取fnumber这个字段值中的第1个字符,而第一句话,Select substring(t.fnumber, 1,1)+substring(t.fnumber, 4,1)+ substring(t.fnumber, 6,4) as abbr,,就是抽取fnumber这字段值中的第一个字符加上第4个字符和第6,第7,第8,第9共6个字符组成的新的字符串,并把这个字段换成新的名字为abbr,这个非常有意义,因为我们后面还可以看到它,而如from AIS20040902164905.dbo.t_organization t
left join AIS20040902164905.dbo.t_settle o
则是从t_organization和t_settle这两个并用左外连接的方式选取数据,left join就是左外连接,意思就是选左表中所有的字段并上右表中有和左表相同的字段的所有值,如果右表中有左表中没有的字段,那么就不选取,如果要选取两个表中不论有相同字段还是没有相同字段,那就用full outer join,如果选择两个中共有的字段,那么就用full inner join,
还有一个是right join,它和left join相反,所以只要表名位置调换,就可以了,所以用得少,再看下,union,相当于数学里面的并集,就是第一段的查询结果并上第二段的查询结果,而且会把相同的记录去除,还有个union all,这样的结果是不会去除重复的行,第一个段的查询结果和第二个段的查询结果记录之和就一定等于union all之后的记录总和,我在接下来的分析之前,要对这一段的内容,有非常充分的理解和掌握,因为我预料到,在后面的transform中,抽取数据库多个表中字段的时候,这个一定要用到,而我也相信,在我充分熟悉之后,我就能非常快的发现其中那些是用错啦,那些没用错!理解这些之后,我开始,总结一下这个表输入总的都做了什么:第一,它把AIS20040902164905中的fnumber字段,取第1,4,6789位组成的取值为第一个新值,把AIS20041216164951中的fnumber字段取第3,6789位组成的取值为第二个新值,而都把结果放在把fnumber字段改名之后的abbr字段中;第二,他也把从两个数据库原来的fnumber放入到了数据流里,这就是这个表输入完成的所有任务。下面,我看表输出,
更简单的是,表输出,第一次创建新表,将新表命名为ar_customer_mapping,
并将其存放在以2.252为连接的数据库dw2005中,我一定要记住这个表,不只因为这个,是第一个transfrom里面的第一个新建的表,更因为,这个表它本身还会被多次使用到,所以珍惜这第一个transform所做的珍贵的成果,它会我后面的分析非常有用!
- 2. 现在开始,我开始看第二个transform,
打开它,可以发现,它比前面我看到的那个要复杂很多,还记得,第一个transform,只有两个entry,而这个居然有13个之多,我按照数据流方向,从第一个,表输入开始研究,打开它,这是来之以2.3为连接的数据库,我看到好多好多的SQL代码,不过别急,慢慢来,看他人的劳动成果的时候,总是需要特多的耐心,所以,我分段来分析它,看到第一段如下
SELECT invoice_no AS INVOICE_NO, Customer AS abbr, invoice_amt AS INVOICE_AMOUNT, due_date AS INVOICE_DUEDATE,
currency AS INVOICE_CURRENCY, desc_eng AS INVOICE_PAYMENTTERM, cp_dept AS INVOICE_DEPT, hk_data AS INVOICE_DATE, Substitute,
buyer_name_eng AS BUYER, label AS LABEL, division AS DIVISION, season AS SEASON, Shipment_Date AS REQ_DATE, Merch_Incharge AS CUSTOMER_MR,
garment_no AS GARMENT_NO, Style_No AS STYLE_NO, Sales_by AS SALES_BY, cp_quyu AS REGION, fabric_name AS FABRIC_NAME, color_name AS COLOR_NAME,
unit_price AS VATNO_DJ, Cust_PO AS PO, Mo_No AS MO_NO, Inland_By AS MR, Pieces AS QTY2, cp_unit2 AS QTY2_UNIT, quantity AS QUANTITY,
quantity_unit AS QUANTITY_UNIT, payment_qty AS PAYMENT_QTY, cp_focqty AS FOC_QTY, unit_code AS UNIT_DJ, cp_focamt AS FOC_AMT,
commission AS COMMISSION, discount AS DISCOUNT, Destination AS PORT_NAME, po_type AS SAMPLE_TYPE, pi_price AS PI_PRICE,
pi_unit AS PI_PRICE_CURRENCY, pi_qty AS PI_QTY, pi_qty_unit AS PI_QTY_UNIT
FROM (
我们姑且先不看FROM后面的表名到底是什么,这里提供给我们的是一大把一大把的字段,从邮件中我了解过,这些字段都是经常看到的那些,尤其是我刚在前面看到的那个abbr字段,在这边是直接由customer而换名而来,其他字段也特别值得注意,如erch_Incharge AS CUSTOMER_MR,一样在邮件中刚刚提及,记住他们,这些主要的字段。熟悉了这字段群之后,开始看下面一段
case when isnull(Shipment_fabric.piece_unit, 'R') = 'R' then 'ROLLS'
when isnull(Shipment_fabric.piece_unit, 'R') = 'P' then 'PACKAGES'
when isnull(Shipment_fabric.piece_unit, 'R') = 'B' then 'BAGS'
when isnull(Shipment_fabric.piece_unit, 'R') = 'C' then 'CTNS'
when isnull(Shipment_fabric.piece_unit, 'R') = 'E' then 'CONE'
when isnull(Shipment_fabric.piece_unit, 'R') = 'A' then 'BALES'
when isnull(Shipment_fabric.piece_unit, 'R') = 'S' then 'SET' end as cp_unit2,
我们先分析一下这个isnull函数,isnull(A,replacevalue)=H,其中A可以是任何类型的数据,replacevalue是当表达式结果为存在H时,那么就执行then后面的替换,其实本来这个函数是一般不用等号的,直接用变量代替上面的R就好,不过可能是作者觉得这样更方便,所以用等号的方法。 如isnull(Shipment_fabric.piece_unit, 'R') = 'P' 完全可以用
isnull(Shipment_fabric.piece_unit, 'P')代替,这样就更容易看懂了,
case when then是一个分支语句,在这里是对数据值的分类,如
select (case province when '广东省' then '广东' when '江西省' then '江西' else province end ) as 省份 from student
Ok,end when then end 分析完了,对了,还有最后一个end as cp_unit2,
cp_unit2,很显然这个是字段的名字,就是把原来的piece_unit换成了新名字cp_unit2。这段代码所做的工作就是把他们进行了字段值的重新分类和字段的改名。下面我看下面一段代码:
FROM dbo.Shipment_fabric WITH (nolock) inner JOIN dbo.invoice WITH (nolock) ON dbo.Shipment_fabric.Invoice_no = dbo.invoice.invoice_no
left JOIN dbo.Orders WITH (nolock) ON dbo.Shipment_fabric.order_id = dbo.Orders.Order_ID
left JOIN dbo.Orders_Assortment WITH (nolock) ON dbo.Shipment_fabric.color_id = dbo.Orders_Assortment.Color_ID
substring(dbo.invoice.invoice_no,1,1) in('B','M')
UNION ALL
SELECT distinct
dbo.invoice.Invoice_no,
dbo.invoice.customer,
'色布' as p_type,
dbo.invoice.charge_amt as invoice_amt,
dbo.invoice.due_date,
dbo.invoice.currency,
大家在写查询时,为了性能,往往会在表后面加一个nolock,或者是with(nolock),其目的就是查询是不锁定表,从而达到提高查询速度的目的。,这里还用到了一个我们在第一transfrom的时候提到的UNION ALL,就是表示留下重复记录行,是对整个记录即行而言的,第二点我要记住的是distinct,就是去除重字段值,是对表中单个地段而言的。
这一段代码的作用就是从这么多的表中选取某些字段的值,接着我看下面的代码:
dbo.orders_fabric.unit_code,
(isnull(case when dbo.shipment.quantity_unit ='LBS' or isnull(dbo.shipment.quantity_unit,'') = '' then dbo.shipment.quantity
when dbo.shipment.quantity_unit ='YDS' or dbo.shipment.quantity_unit = 'BAG' or dbo.shipment.quantity_unit = 'BOT' or dbo.shipment.quantity_unit = 'BOX' then dbo.shipment.yard
when dbo.shipment.quantity_unit ='KGS' then round( dbo.shipment.quantity /2.2046,2)
when dbo.shipment.quantity_unit ='MTS' then round(dbo.shipment.yard *0.9144,2)
when dbo.shipment.quantity_unit ='PCS' then dbo.shipment.yard
when dbo.shipment.quantity_unit ='SET' then dbo.shipment.quantity2
when dbo.shipment.quantity_unit ='DOZ' then case when isnull(dbo.shipment.quantity2,0)=0 then dbo.shipment.yard /12
else
这段代码的涉及到的逻辑比较深,一开始我看不懂,其实就是在原来when case then end 的基础上加上了多个条件的判断条件执行语句,并没有特别复杂。这里我跳过这段解释,我看完后面的代码,发现所有的语句几乎和前面的格式一样,只不过是换了表和字段而已,现在我来总结一下这整个SQL语句所做工作:
首先可以确定,这个表输入只涉及一个数据库2.3里面的kamhing,涉及的表有
invoice,
payment_term,
buyer_label,
Shipment,
Shipment_fabric,
Shipment_Out_Dtl,
Orders,
Orders_Assortment,
Orders_Assortment_rec,
orders_fabric,
Orders_Fabric_Specs,
Orders_Fabric_Specs_rec,
从这整个SQL编辑区从上至下分析,每一个好长好长的case when
Then else end 语句最终的结果都只是返回一个字段,所以我分析它的时候,可以越过这些非常漫长的判断,这样的话就会简洁得多,只要看完了第二个select至Union all之间的部分,后面的部分语法完全一样,选择的表和字段也一样,只是判断的条件不同,所需的字段值不同,看看下面这段内容
FROM dbo.Shipment WITH (nolock) INNER JOIN dbo.invoice WITH (nolock) ON dbo.Shipment.Invoice_no = dbo.invoice.invoice_no
INNER JOIN dbo.Orders WITH (nolock) ON dbo.Shipment.order_id = dbo.Orders.Order_ID
INNER JOIN dbo.Orders_Assortment_rec WITH (nolock) ON dbo.Shipment.color_id = dbo.Orders_Assortment_rec.Color_ID
INNER JOIN dbo.Orders_Fabric_Specs_rec WITH (nolock) ON dbo.Shipment.fabric_id = dbo.Orders_Fabric_Specs_rec.Fabric_ID AND
dbo.Orders_Assortment_rec.Specs_ID = dbo.Orders_Fabric_Specs_rec.Specs_ID
left Join dbo.buyer_label with(nolock) on dbo.Orders.buyer_code = dbo.buyer_label.buyer_code
left join dbo.orders_fabric with(nolock) on dbo.orders_fabric.fabric_id = dbo.Shipment.fabric_id
left join dbo.payment_term with(nolock) on dbo.orders.pay_term_code = dbo.payment_term.term_code
WHERE SUBSTRING(dbo.invoice.invoice_no, 1, 1) = 'D' AND dbo.invoice.invoice_type = 'C' and ( shipment.confirm_flag
> 0 )
这样把这么多字段连接在一起之前,需要对这些字段之间原来的联系要有足够的了解,这里涉及到ERP系统生产中,对于我,没有了解过哪些来说,切实有点复杂;所以,首先先记下它,至于那几个表为什么会有这种千丝万缕的联系,后面会明白的。接下来,整体分析一下这所有SQL查询过程中都做什么:第一步,先从刚列出来的那12个表中,对那些有单元划分的字段进行分类,按照相互之间的联系把那些关于货运相关的运费子类的字段筛选出来组成一个新表,其名derivedtbl_1;第二步,在第一步的基础上,从中筛选出最终需要的字段,这就是整个SQL所做的工作。接下来,我需要看另外一个tableinput,打开它,看到同样是以2.3为连接的kamhing数据库数据源,下面的代码
SELECT distinct Shipment_fabric
dbo.Shipment_sample.Invoice_no,
dbo.invoice.customer,
'色布' as p_type,
Round(dbo.Shipment_sample.payment_qty * isnull(shipment_sample.vatno_dj,0),2) as invoice_amt,
dbo.invoice.due_date,
dbo.invoice.currency,
dbo.payment_term.desc_eng,
'船務部' as cp_dept,
dbo.invoice.hk_data,
dbo.Orders.Substitute,
buyer_label.buyer_name_eng,
buyer_label.label,
buyer_label.division,
dbo.Orders.SEASON,
dbo.Orders.shipment_date,
dbo.Orders.merch_incharge,
dbo.Orders.garment_no,
dbo.Orders.style_no,
dbo.Orders.sales_by,
case when dbo.Orders.groups = 'CN' then '中國區'
when dbo.Orders.groups = 'HK' then '香港區'
when dbo.Orders.groups = 'KR' then '韓國區'
when dbo.Orders.groups in('SA','SB','SC','SD') then '新加坡區' end as cp_quyu,
我看到,这里和刚刚那个表输入不同的是所选择的表对象多了一个,
Shipment_sample表,这里的Shipment_sample就犹如刚刚Shipment_fabric,而判断条件等等几乎相同,通过下面这一段,分析一下所牵涉的表
left JOIN dbo.Orders_Assortment WITH (nolock) ON dbo.Shipment_sample.color_id = dbo.Orders_Assortment.Color_ID
left JOIN dbo.Orders_Fabric_Specs WITH (nolock) ON dbo.Shipment_sample.fabric_id = dbo.Orders_Fabric_Specs.Fabric_ID AND
FROM dbo.Shipment_sample WITH (nolock) inner JOIN dbo.invoice WITH (nolock) ON dbo.Shipment_sample.Invoice_no = dbo.invoice.invoice_no
left JOIN dbo.Orders WITH (nolock) ON dbo.Shipment_sample.order_id = dbo.Orders.Order_ID
dbo.Orders_Assortment.Specs_ID = dbo.Orders_Fabric_Specs.Specs_ID
left Join dbo.buyer_label with(nolock) on dbo.Orders.buyer_code = dbo.buyer_label.buyer_code
left join dbo.orders_fabric with(nolock) on dbo.orders_fabric.fabric_id = dbo.Shipment_sample.fabric_id
left join dbo.payment_term with(nolock) on dbo.orders.pay_term_code = dbo.payment_term.term_code
WHERE ( substring(dbo.invoice.invoice_no,1,1) = 'A' ) and (dbo.invoice.invoice_type = 'C')
) as adad
上面我画出来的地方,就是这整个表输入涉及到的表,比起刚才的表输入来,这个表输入,因为涉及的表操作没有刚刚那么多,所以少了很多工作量,不过逻辑还是一样的。通过上面这段代码,总结一下这个表输入所做的工作:第一步,从列出来的表中,按照他们之间的关联字段,通过先对那些分类字段的取值进行分类,赋新值,然后再组成一个新表adad,第二步,从这个新表中抽取那些需要的字段,这就是整个表输入完成的任务。看了半天,终于把这两个表输入的内容给看完了,感觉松了一口气,但是我也知道,这里面的部分,最终还是要回头来研究,因为这里涉及到的部分,韵味深长,这是整个数据筛选的最为重要的部分,这里发生了重要而大量的数据变换,而现在我先告一段落,开始分析下一个entry.
在第二个表输入的流前面,看见了Javascript,其实写下记录,是一个非常好的复习和学习的过程,如果遇到了认识的,那就是一个复习和深化的历程,如果是没学过的,那就是重新学习那些,这里面的JavaScript,我的基础还真不是很好,只是曾经我是亲微软的,当初在学C#编程的时候,看到其他人开发的系统和网页有过这些,那时候就接触了它,所以不熟悉,同样,也不陌生,看到下面的这段代码,开始看看它到底做了什么
函数名(参数)
function transCol2ToCol1(col1, col2, num
)
{
var trimedcol2;
var col2length;
if(col2==null||trim(col2)==" "||trim(col2)=="")
{
if (col1==null||trim(col1)==" "||trim(col1)==""){
return " ";
} 正则表达式
每行第4个空格替换成换行符
return col1;
}
trimedcol2=trim(col2.replaceAll("[^\x00-\xff]","11"));
col2length=trimedcol2.length;
if(col2length<=num&&col2length!=0){
return col2;
}
else if (col2length>num&&(col1==null||trim(col1)==" "||trim(col1)=="")){
var ch,bytenum=0;
var rs = "";
var pt = /[^\x00-\xff]/;
for (var i=0; i < num; i++)
{
ch = col2.substr(i, 1);
if (ch.match(pt))
{
bytenum += 2;
if (bytenum > num)
{
return rs;
}
}
else{
bytenum += 1;
}
rs += ch;
if (bytenum == num){
return rs;
}
}
return rs;
}
else{
return col1;
}
}
MO_NO.setValue(transCol2ToCol1("",MO_NO.getString(),30));
看的出来,上面的脚本就是先定义了一个处理的函数,所谓函数,只是翻译成中文是函数,在英文中的本名叫做功能,作用,就是把一个功能封装在一起,加上调用所传递的参数,最后一行,就是调用了这个函数来处理MO_NO这个字段,使那些符合条件的内容变为空值。
这段代码我有些看不懂,因为以前这种编程的循环好像和这个有点不一样,所以有点特别。我想写跳过去,以后再慢慢琢磨。
下面看到append streams,
这可能是这里看到的最简单的一个entry了,它仅仅是把两条数据流中的数据进行汇合在一起,但条件是这两个数据流中的字段必须相同。这样才能汇合。使用操作也非常简单。第一个方框中输入给他取的名字,第二个方框中输入第一个选择的流源,第三个选择第二个数据流来源,这样点击OK就把两边的数据合到一个了,别看它使用起来这么简单,可它的作用是非常大的。从这里,我可以反思一下,刚刚两边的表输入,他们分别获取的字段是完全相同的,而且最后的字段数据类型也一样要分别对应,现在,这里汇合之后,这里成为了整个transform里面的所有数据源,从这里开始,下一步就是数据处理部分了。我接着,打开Database lookup,
先复习一下,这个entry,其实,这里面的每一个entry,都是一个函数的聚合,这里应该这样理解,它就像我们在编程时候写下的函数,当我们需要调用它们的时候,我们就要输入或者选择好参数,函数根据我们提供的参数,再去执行任务,最后返回结果,而Database lookup,其实和表输入一样也是数据源的一种,先谈谈look up的英文意思,它的意思是查找的意思,可以知道,这里就是查找另外一个表中某些字段的值,然后添加到这个流中,因为它也是获取数据源的一种,所以他也和数据库有连接,打开它,我看到,它的数据来源来之2.252为连接的ar_customer_mapping表,我非常深的记得,这个表是在第一个transform的时候创建的,客户编码的那个,仅仅是对fnumber字段的值进行了分类,然后把其中部分换成了新的字段值,这样的而已,所以现在从这里把它用上了,所以当初我说要记住它,现在真的用上了,这这边,这是一个非常需要记住的内容。现在明白,千万别怪作者太罗嗦,其实他把这个系统弄得这么复杂,也是没有办法的,这就好比SQL语言中,我查询数据库里面字段值的时候,当经常涉及到一些复杂查询的时候,就经常要分成多个步骤,在第一个步骤的基础上,再查找,这结果就是第二个步骤的结果,在第二个结果的基础上查找得到结果3,如此循环往复,这样其实本来就是为了简化问题,使问题更符合我们的逻辑,一般人更容易懂,也更不容易出错,但是在数据设计部分,我曾经看过oracle方面的书,那些说提高效率的往往反对使用多重查询,因为这样会降低效率,使效率很低,但是没有办法啊,这里至少现在只能如此。也许我这里说得太多,但是,相信这是一个非常重要的思想,从Kettle的设计当中我想起了SQL语言,因为他们本身就是同体,这上面所说的思想我觉得是我慢慢看,然后体会出来的,这种体会,我想对我会很有帮助的,我相信,我在领会这个的基础上,对我以后去设计从庞大而复杂的数据源中获取数据,再进行清洗和加工,进行编号的时候,这个会有非常大的作用,创建中间表,准备好数据表,就是先设计好的一种构架。很幸运的是,作者并没有把那些获取数据源的步骤的架构图给我,而让我慢慢自己去探索,我探索出来的,是一个还不完整,但是正在完整的过程,它能深入我的大脑中,所以,这段日子里,我要花足够多的思维去领悟剩下的,怀念以前的。
我看到第一个编辑框,The key(s) to look up the value, 这个
故名思义,两个表之间共有的字段,这里把他叫做key,其实在各自的表中,它未必一定就要是主键,就是说这里的key,和数据库中的key是有所不同的,哪里的key不是主键就是外键,而这里我看到,其实慢慢的就能理解,为什么要有两个表中的共有字段呢?因为如果没有共有字段的话,那么添加字段的时候,就没有参照,没有参照多条记录合在一起的时候,就只能按照默认,而那样就很可能导致错乱,所以就一定要有共有字段。而第二个编辑框,诸Values to return from theLook up table,也不难理解,就是查找的那个表中要返回的字段,这里选择了fnumber,其实我还记得,这个表中无外乎abbr和fnumber这两个字段,在这里我才知道,它给他重新字段改名为cust_name其实就是客户名字的意思。好了,这里OK了,我接着看下一部分的内容。打开value mapping,,
先谈一下mapping,因为这个数据库世界里,我要常常和她见面,原词本是map,地图之意也,mapping是一个动词,筹划,映射,地图的意思,所以现在这里应该是映射值,就是把某些字段的值进行映射,如汉子里面的成绩优,良,不及格三等级映射为英文里面的A,B,C,所以这样也就容易理解了。
好了,接着下一个entry,select values, 一样,一点也不陌生,即为筛选值,专业点,就是过滤,过滤就是选取那些想要的字段,这里有三个编辑框可供选择,第二个是Remove,当我们在第一个编辑框中把所有字段都选进来了的时候,这个编辑框就其作用了,可以把那些不要的,少部分不要的字段给T掉,所以这也不是多此一举,而是帮我们节省了时间,第三个编辑框,meta data,其中meta是变换之意,其实在第一个编辑框SELECT&ALTER就已经有这第二和第三编辑框的功能了,这里之所以加上重命名字段的部分,是为了更加方便,其实作用是相同的。好了这里看完了,接着看下一部分的内容。Filter rows,
千万别说错啦,其实刚刚我也说过select values这个entry也是筛选功能,select values是针对字段的选取,而这里是针对字段里面值得选取,看到编辑框我知道,这里选取字段为INVOICE_NO进行判断,如果值以A,H,D开头的发票号码,则不需要进入下一环节。到这里,由于上次我觉得其他也一样,所以直接进入下一个entry了。Sort rows,
对行排序,行排序,就是选择好字段之后,按照字段值降序或者升序排序,AS为升序,DS为降序的意思,后面一个列显示的sensitive compare, 我知道英文意思是敏感对比,因为是敏感对比,我理解是应该是在同样值得情况下,会按照一定的方式编排顺序,这个因为可能容易引起错误。现在到了groub by了,
groub by,毫无疑问,是按照组分类的意思,这个在SQL中我常遇到过,在这里我举一个不带截图的例子:从一个班级中选择所有人的名字,学号,性别和成绩,如果选好字段按性别分组,然后再选择按成绩分组排序,那么先按性别分成两组,一组为男生,一组为女生,在男生那半部分,以男生的成绩排序,在女生那部分,以女生的成绩排序,所以group by 这里也是这样的意义。这里的下面一栏,aggregate,
就是聚合,合计的意思,在这里,是把那些关于数值型的值给聚合,比如分类,求最大值,求最小值,求平均值,方差等等这个值,可以直接放在本字段的末尾,如果放在末尾,那么这里我就要在Subject中选择和前面相同的,如果不这样,可以写一个新的名字,那么这样下来,就创建了一个新的行,来存放这个聚合值。当然我现在的理解即是如此。这一点,在后面我依然需要加强,现在到下一步,
又是javascript,这个JavaScript编辑框中,的上半部分,比起刚刚那个javascript来,可是要来得简单很多,
if (substr(INVOICE_NO,0,1)=='H')
{
INVOICE_TYPE="5101.03.05.02";
INVOICE_SUBTYPE="5101.03.05.02";
}
if (substr(INVOICE_NO,0,1)=='M')
{
INVOICE_TYPE="5101.03.05.01";
INVOICE_SUBTYPE="5101.03.05.01";
}
if (substr(INVOICE_NO,0,1)=='A')
{
INVOICE_TYPE="5101.03.05.04";
INVOICE_SUBTYPE="5101.03.05.04";
}
if (substr(INVOICE_NO,0,1)=='D')
{
INVOICE_TYPE="5101.03.05.02";
INVOICE_SUBTYPE="5101.03.05.02";
}
我非常清楚的记得,在第一个tarnsfrom的时候,还是在其他地方的时候,曾经都遇到过这样类似的,substr,你懂的, 分部取值的意思。当第一个字母是什么什么的时候,就执行IF括号里面的内容,在第二个编辑框中,新增加的两个字段就是这样作用的。看到本transfrom,达到了最后一个entry,我终于松了一口气,表输出,很是简单的一个部分,这里就是把前面所有做好的数据发送到目标表中,这个表名输入进去,如果这个表名在目标数据库中已经有的话,那就不用再闯几年了, 有个前提,就是这个表中的字段和流中最后的字段必须相同且字符类型也相同,不然就会运行出错,所以一般我们都是写一个原来数据库中不存在的表名,既然不存在,那么现在就要用SQL语言通过kettle去创建这个表,点击SQL按钮,然后执行,就可以成功创建一个表。最后运行就能把所有的数据输入那个表中。
到了这里,我看见了那个非常伟大的2.252为连接的import_temp表,这个表在我刚开始分析AR的时候,就深知其重要性。所以记住它。到这里,这个tranform
分析完了。下面我总结一下这整个transfrom所做的工作:
从2.3中抽取的船务信息,进行分类、清洗转换,再加上第1个transform从K3_Hk编好的客户编码系统,最后进过过滤筛选,字段更新操作,最后导入到了2.252的import_temp,所以这里最为重要的部分,就是前面部分,同时这也是在第一个transform的基础之上,才能做的工作。
3.现在开始,我分析第三个transform
打开这个transform,当我刚接触前面部分的时候,感觉是这么的吃力,
因为这里的部分,它总是涉及那么多的代码,涉及那么多的代码,我在第2个transform中,从一开始的眼花缭乱到找出规律,是一个从复杂到简单的过程,所以我已经有了耐心,现在打开它,又一个复杂点的表输入。
在这里,只要我记录到的地方,我都会用画笔把它画出来,因为这样更方便回忆,看前面部分的代码
SELECT
a.invoice_custom_no as 'INVOICE_NO',
a.customer as 'abbr',
b.fabric as 'FABRIC_NAME',
round(b.units * b.fact_quantity, 2) as 'INVOICE_AMOUNT',
a.money_type as 'INVOICE_PAYMENTTERM',
a.money_date as 'INVOICE_DUEDATE',
b.unit_type as 'INVOICE_CURRENCY' ,
c.footnote as SALES_BY,
e.sales_notes as REGION,
space(10) as 'INVOICE_DEPT',
c.inland_by as 'MR',
a.f_date as 'INVOICE_DATE',
c.substitute as 'BUYER',
space(10) as 'DILIVERY_DATE',
c.shipment_date as 'REQ_DATE',
c.customer_by as 'CUSTOMER_MR',
c.style_no as 'STYLE_NO',
a.mo_no as 'MO_NO'
FROM invoice_custom a with(nolock),
invoice_custom_detail b with(nolock),
orders c with(nolock),
salesman e with(nolock)
这个以ds_erp为数据源和ds_erp为数据库的表输入,比起第二个transform来可是要来得简单很多很多,如果按照union 来划分的话
可以分成6部分,但是中间四部分都是从完全相同的表中抽取相同的字段,只是Where之后的条件判断不同,所以,当初邮件中有分析任务的时候,我一直在看这个,所以就看出来了规律,现在,把中间四个相识的再抽取一个出来
select a.invoice_no as 'INVOICE_NO',
a.bill_customer as 'abbr',
b.Fabric_Name as 'FABRIC_NAME',
round(b.payment_qty * b.price, 2 ) as 'INVOICE_AMOUNT',
a.payment as 'INVOICE_PAYMENTTERM',
a.due_date as 'INVOICE_DUEDATE',
a.currency as 'INVOICE_CURRENCY',
c.footnote as SALES_BY,
e.sales_notes as REGION,
space(10) as 'INVOICE_DEPT',
c.inland_by as 'MR',
a.hk_data as 'INVOICE_DATE',
c.substitute as 'BUYER',
space(10) as 'DILIVERY_DATE',
c.shipment_date as 'REQ_DATE',
c.customer_by as 'CUSTOMER_MR',
b.style_no as 'STYLE_NO',
b.mo_no as 'MO_NO'
from invoice a with(nolock),
V_Comm_List_Detail b with(nolock),
orders c with(nolock),
salesman e with(nolock)
where a.invoice_id = b.invoice_id
and ( a.invoice_type = 'C' or a.invoice_type is null )
and a.c_type=0
and a.cancel_flag = 0
and a.confirm_flag = 2
and b.mo_no = c.mo_no
and c.footnote = e.sales_name
and a.hk_data >='2011-1-1'
一段并不复杂的关联表查询,和我平时练习的时候看到的,仅仅是多了几个字段而已,连表也不怎么多,而现在需要熟悉的是这些字段
因为这是数据源,这里筛选出来的字段,一定是和目标地点有关系的,有的是需要经过改名、替换清洗等等,正是因为他们会经过各种变换,所以现在需要对他们本来是谁要记住。还有一个是在分析第一个transform的时候,曾经温习过的,union all和union 的区别,因为那天晚上,给我留下非常深刻的印象,下面我再举一个非常好的例子:
请注意,UNION 内部的 SELECT 语句必须拥有相同数量的列。列也必须拥有相似的数据类型。同时,每条 SELECT 语句中的列的顺序必须相同。
SQL UNION 语法
SELECT column_name(s) FROM table_name1
UNION
SELECT column_name(s) FROM table_name2
注释:默认地,UNION 操作符选取不同的值。如果允许重复的值,请使用 UNION ALL。
SQL UNION ALL 语法
SELECT column_name(s) FROM table_name1
UNION ALL
SELECT column_name(s) FROM table_name2
另外,UNION 结果集中的列名总是等于 UNION 中第一个 SELECT 语句中的列名。下面的例子中使用的原始表:Employees_China:
E_ID | E_Name |
01 | Zhang, Hua |
02 | Wang, Wei |
03 | Carter, Thomas |
04 | Yang, Ming |
Employees_USA:
E_ID | E_Name |
01 | Adams, John |
02 | Bush, George |
03 | Carter, Thomas |
04 | Gates, Bill |
使用 UNION 命令列出所有在中国和美国的不同的雇员名:
SELECT E_Name FROM Employees_China
UNION
SELECT E_Name FROM Employees_USA
结果
E_Name |
Zhang, Hua |
Wang, Wei |
Carter, Thomas |
Yang, Ming |
Adams, John |
Bush, George |
Gates, Bill |
注释:这个命令无法列出在中国和美国的所有雇员。在上面的例子中,我们有两个名字相同的雇员,他们当中只有一个人被列出来了。UNION 命令只会选取不同的值。
UNION ALL
UNION ALL 命令和 UNION 命令几乎是等效的,不过 UNION ALL 命令会列出所有的值。
使用 UNION ALL 命令实例:列出在中国和美国的所有的雇员:
SELECT E_Name FROM Employees_China
UNION ALL
SELECT E_Name FROM Employees_USA
结果
E_Name |
Zhang, Hua |
Wang, Wei |
Carter, Thomas |
Yang, Ming |
Adams, John |
Bush, George |
Carter, Thomas |
Gates, Bill |
因为我们这里用的是union all,所以我怀疑它会把那些重复的结果显示出来,这样的话,如果在这个基础上算合计总和的话,就会出错,虽然说后面的判断条件有的不同,但是如果恰好碰到了相同的结果的话,那么重复就出现了,本数据表结果没有任何主键,所以难保证所有的值都不重复,所以最好的方法,是在所有的表中都尽量添加主键,这样出错的概率就小了,查找数据和处理数据都简便得多。
这里开始进入下一个entry,
Database lookup,,由于在前面第2个transform的时候,我已经详细的了解过它的function,作用,所以我这里仅仅需要看着这个图回忆一下即可了,拿出上次那个Database lookup,和这个完全一样,查找的是一样的表ar_customer_mapping,取的是一样的字段,abbr为参照键,还说过,这里的key和数据库中的不完全相同,这里的fnumber也一样。
进入下一个entry, ,Select values,选择字段,当初我还说过,select values和filter rows的区别,前者是针对字段的,
就是选择那些字段,它还有三个编辑框,其中第一个编辑框里面有第二和第三个编辑框中全部的内容,后者是针对字段里面的数据值而言的,当需要它的值得时候,就使用它。 ,这个和我在第2个transform里面看到的也完全一样,下面是
排序,排序也是选取了INVOICE_NO,FAB+RIC_NAME,MO_NO3个字段以升序的方式排序,回忆了分组group by,现在我再用一个例子来回忆SQL中,合计函数 (比如 SUM) 常常需要添加 GROUP BY 语句
SQL GROUP BY 语法:
SELECT column_name, aggregate_function(column_name)
FROM table_name
WHERE column_name operator value
GROUP BY column_name
我拥有下面这个 "Orders" 表:
O_Id | OrderDate | OrderPrice | Customer |
1 | 2008/12/29 | 1000 | Bush |
2 | 2008/11/23 | 1600 | Carter |
3 | 2008/10/05 | 700 | Bush |
4 | 2008/09/28 | 300 | Bush |
5 | 2008/08/06 | 2000 | Adams |
6 | 2008/07/21 | 100 | Carter |
现在,我们希望查找每个客户的总金额(总订单),
我们想要使用 GROUP BY 语句对客户进行组合。
我们使用下列 SQL 语句:
SELECT Customer,SUM(OrderPrice) FROM Orders
GROUP BY Customer
结果集类似这样:
Customer | SUM(OrderPrice) |
Bush | 2000 |
Carter | 1700 |
Adams | 2000 |
很棒吧,对不对?
让我看一下如果省略 GROUP BY 会出现什么情况:
SELECT Customer,SUM(OrderPrice) FROM Orders
结果集类似这样:
Customer | SUM(OrderPrice) |
| |||
Bush | 5700 |
| |||
Carter | 5700 |
| |||
Bush | 5700 |
| |||
Bush | 5700 |
| |||
Adams | 5700 |
| |||
Carter | 5700 |
| |||
| 上面的结果不是我想要的 那么为什么不能使用上面这条 SELECT 语句呢?解释如下:上面的 SELECT 语句指定了两列(Customer 和 SUM(OrderPrice))。"SUM(OrderPrice)" 返回一个单独的值("OrderPrice" 列的总计),而 "Customer" 返回 6 个值(每个值对应 "Orders" 表中的每一行)。因此,我得不到正确的结果。不过,已经看到了,GROUP BY 语句解决了这个问题。 GROUP BY 一个以上的列我也可以对一个以上的列应用 GROUP BY 语句,就像这样:SELECT Customer,OrderDate,SUM(OrderPrice) FROM Orders GROUP BY Customer,OrderDate 好了,Groub by,理解了,现在 Javascript出现了,仔细琢磨一下下面这段熟悉的代码的时候到了 第1个if 判断,如果INVOICE_NO的第1到3个字符为CNS或者为DNS,就将字段INVOICE_TYPE值设为5101.03.05.09,再判断CUST_NAME,如果第一到第四个的值为C001,那么INVOICE_SUBTYPE赋值5101.03.07.01,否者赋值5101.03.07.02,这里有个函数getBigNumber(),因名称,是获取大写,就是如果是小写的话,就把小写改成大写。总结一下这个JS做的工作: 这里就涉及5个字段 INVOCE_NO, INVOCE_AMOUNT, INVOICE_TYPE, INVOICE_SUBTYPE, CUST_NAME 先按照INVOCE_NO进行分类,再将 INVOICE_TYPE赋予值,在一定条件下也赋予INVOCE_SUBTYPE,但是如果INVOICE_NO的前3位为CNS或DNS,赋予INVOCE_TYPE值之后,还要对其CUST_NAME进行判断,然后在赋予不同的INVOICE_SUBTYPY值。最后,如果这个INVOCE_NO以CNS开头,则将其INVOICE_AMOUNT设为负数的值,这上面所说的都是原来没有修改之前,保存下来的时候所见到的内容,下面是后来修改的部分 这里后面添加了对INVOICE_PAYMENTTERM赋值的部分。这里很简单,记住这里付款类型中,只要INVOICE_NO以CNS或DNS开头的就赋予T/T的付款类型,且字段DN_FLAG 也分别赋值CNS和DNS,记住这里是修改后的内容即可。在最后面下面这里我还知道 这两个字段是新加的 到了这里,这个transform就到最后一个表输出了 很熟悉的部分,和第2个transform一模一样的输出,一样的数据库,一样的表,最后强调的一点,就是这里因为原来在第二个tansform中创建好了表结构,所以这里就不用创建表了,但是这里的字段值必须和原来创建好的表一模一样。到了这里,总结一下这第3个transform所完成的全部任务: 第一,从ds_erp数据库中抽取客户发票相关的表中抽取字段,重新命名,然后再和第一个transform中的创建的客户编码对应系统表对应,然后再重新筛选字段,过滤数据值,排序,分类,添加字段,最终将数据导入import_temp.这里,这第3个transform就分析完了。这里的第一个部分,表输入依然是以后需要回来光顾的地方。 4.现在开始,我看第4个transform 从取得名字中可以看出,船务系统取消单和船务系统发票是有关系的,可以预料,它是和第2个tranform是抽取的相同的部分,但是只是那些取消的内容,现在我打开它
这个表输入非常简单,仅仅是从2.3的INVOCE中选取了几个字段,条件只有两个hk_data和cancel_flag,我要记住,这是再次从2.3这里去数据,再看后面的 addcolumn, ,这是其中的一段代码,因为这整块代码都比较简单,这里和第3个transform一样,都是判断INVOVICE_NO,新添加了两个字段,为INVOICE_NO和INVOICE_SUBTYPE。 后面看到Insert/Update,一个前面没有了解过的工具,按照其英文意思,即为插入和修改,打开它把它分成三部分 这是第一部分的话,那么,这里算是表的名字,这里的表名几乎和我前面看到的2个transform一样都为import_temp,现在,我们看第二部分 这里的部分和我在Database lookup看到的几乎一样,现在把Databaseklook up 拿出来
几乎一样的吧,从这里可以看出,kettle这个工具里面的插件,很多其实都是套用的模块,相当于编程里面的模块重用。回到刚才的Insert/Update, 它的这一部分的意思,也应该是参照字段,要把数据插入到别人的表中,就像坐火车一样,都是对号入座的。所以,为了使数据不会混乱,就产生了这么一个参照字段,当然这里的参照字段可以有很多个,但是如果觉得一个就够了,那最好,我觉得就用一个,因为这样可以提高效率。下面部 这里是用这里数据流中的数据来更新import_temp表中原来的数据,我想,这里应该是把那些取消了的发票相关的记录的值改变。到了这里,第4个transform分析完了。总结一下这一个transfrom做了什么: 从2.3所在的数据库的INVOICE表中,抽取那些意为取消了的字段,然后 用Javascript添加两个新的列,然后再把这些改变的添加到import_temp中,如果那些表中的数据相同的,那么就修改它。 很简单吧。 5.现在开始,我分析第5个transform
纱厂系统取消单,对应于第3个transform,打开它,打开第一个表输入,其是从ds_erp抽取数据,一段代码如下 union all SELECT a.f_number as 'INVOICE_NO', c.Abbr as 'abbr', b.f_description as 'FABRIC_NAME', b.f_money as 'INVOICE_AMOUNT', '' as 'INVOICE_PAYMENTTERM', null as 'INVOICE_DUEDATE' , '' as 'INVOICE_CURRENCY' , '' as SALES_BY, '' as REGION, space(10) as 'INVOICE_DEPT', '' as 'MR', a.f_date as 'INVOICE_DATE', '' as 'BUYER', space(10) as 'DILIVERY_DATE', null as 'REQ_DATE', '' as 'CUSTOMER_MR', '' as 'STYLE_NO', '' as 'MO_NO' FROM tab_debit a, tab_debit_detail b, Customer c WHERE ( a.f_number = b.f_number ) and ( a.customer = c.Abbr ) and ( a.f_date >= '2011-01-01 00:00:00' ) and ( a.mat_type = 'Y' ) and a.f_cancel = 1 这是一部分非常熟悉的代码,其实这整个和第一次分析union all那段代码是几乎一样的,现在我要看他们之间选择条件不同的地方。这里的f_cancel=1 而那边的f_cancel=0,这是最为显著的地方。现在对比一个第一段的代码 这是这里的部分 这是第3个transform的部 我说对了吧,这里仅仅有一个字段值取值不同,现在这里是取,1边是取0 因为在原数据库中,如果取0那么代表没有取消,如果取1那么代表这里取消了。 这里,我再看下面的5部分代码的对比,但是拘于篇幅所限,也节约成本,因为我相信,大家都很聪明的,所以把结果写下来就好了。
告诉你吧,在后面的部分,未取消的还有个字段,confirm_flag=2, 而在取消这边,这个字段没有在判断条件中出现过。现在比较完了,回到现在分析的表输入来,它都做了些什么呢?就是从ds_erp中抽取那些取消了的数据,而这些数据又涉及好几个表,所以又要把他们先关联在一起,然后成为新的表之后,再用一个select 从中抽取出来,可以预料,它的过程一定会和第3个transform非常相像,因为他们都是把那些相同的数据处理成结果出了字段值而其他完全相同的表。 基于这种预料,我现在看下一个entry, Database lookup 和前面三个transform一样,它又出现了,也许是因为我的专业所影响吧,
也许是因为我看多了佛经的缘故吧,很多时候,我总喜欢去找规律,而现在对于分析这个系统来说,其实也是一个信息分析与预测得过程,虽然现在预测得不多,分析的本质就是通过观察事物的现象而总结出规律,预测其未来发展方向的过程。 看到这个,就算不用看后面的,就可以非常速度的想起那两个熟悉的字段,abbr和fnumber,因为这个表中,仅仅有这两个字段,而当初在第1个transform的对客户信息编码的时候,abbr是通过fnumber分解而出来的。现在因为是好几遍了,现在我先不再仔细研究 它,进入下一步,
这是又一个非常熟悉的步骤,筛选字段,过滤行,排序,分组汇总,添加两个字段,虽然我讨厌重复做一样的事情,然而,很多东西,都是在我重复几遍的时候才发现其特别香醇的地方,也就是其精华所在。 现在让我先不去打开它们,然后慢慢的回忆,他们都做了什么,就拿字段值过滤来说吧,它一样过滤的是INVOICE_NO,add cloumn是添加的INVOCE_TYPE和INVOICE_SUBTYPE,说,谎言,重复一千遍就是真理 这里,歪打正着,形容学习一点也不为过。 现在我打开表输出 厌恶了吧,又是它,我现在分析到了第5个transform,除了第一个,出现的都是它。一句话,这个transform就是从ds_erp那几个表中抽取那些取消了的订单的信息,然后把所有的发票货币数据清零,最后将数据送入import_temp中。 6.现在开始,我看第6个transform
dn,里面包含23个entry,和这个AR_JOB拥有的transfor一样多,可谓涉及颇多,幸运的是只有一个表输入,先看一看它所涉及的字段吧 SELECT ship_debitnote_detail.Debit_type, ship_debitnote_main.Cust_code AS abbr, ship_debitnote_detail.product AS INVOICE_TYPE, ship_debitnote_detail.dn_cat_code, ship_debitnote_detail.Debit_no AS INVOICE_NO, ship_debitnote_detail.Description AS FABRIC_NAME, ship_debitnote_detail.batch + ' ' + ship_debitnote_detail.color AS REMARKS, ship_debitnote_detail.unit AS QUANTITY_UNIT, ship_debitnote_detail.price AS VATNO_DJ, ship_debitnote_detail.cur AS INVOICE_CURRENCY, ship_debitnote_detail.unit_rate, ship_debitnote_detail.cur_rate, ship_debitnote_detail.Commission AS COMMISSION, ship_debitnote_detail.Mo_no AS MO_NO, ship_debitnote_detail.Cust_no AS PO, ship_debitnote_detail.Style_no AS STYLE_NO, ship_debitnote_main.Debit_Date AS INVOICE_DATE, CASE WHEN ship_debitnote_detail.Datatype = 'BEFORE' THEN - abs(ship_debitnote_detail.amount) ELSE abs(ship_debitnote_detail.amount) END AS INVOICE_AMOUNT, ship_debitnote_detail.Datatype, CASE WHEN ship_debitnote_detail.Datatype = 'BEFORE' THEN - abs(ship_debitnote_detail.quantity) ELSE abs(ship_debitnote_detail.quantity) END as QUANTITY 这其中我所标注的字段都很有代表性的,看abbr,invoice_No,MO_NO, INVOICE_DATe,remarks等字段都是以前常见的字段,必须要先对他们有足够的熟悉,还有一点事这个数据源是来自于2.3的customer等表中, WHERE (NOT (ship_debitnote_detail.dn_cat_code IS NULL)) AND (NOT (ship_debitnote_detail.product IS NULL)) AND (ship_debitnote_main.Debit_Date >= '2011-1-1'), 这些是抽取数据的选取条件,这三个条件都很简单。整个数据源就是从客户相关的2.3中抽取货运相关资料,最后输流中。继续往下看 数据进入流中之后,复制到了两个流中, 这个是复制的意思,第1个部分的select values_1选择了 INVOICE_NO和INVOICE_AMOUNT这两个字段,并且将其重新命名为SUM_INVOICE_NO 和SUM_AMOUNT, ,将其按照SUM_INVOICE_NO为升序排列, 再以SUM_INVOICE_NO分组,再将SUM_AMOUNT求和,且设字段为SUM,然后再将其过滤值,例外一端的 选取了如上的20个字段, 然后再按照INVOICE_NO以升序排序,现在就得到了和这端完全相同的表列,所以现在再进行表合并, ,打开它,看到它的结构很简单,前面我并没有 非常详细的研究过它,它是把两个数据源的数据汇合的到一处的,就像河流一样把水汇合到一起一样,那种三条河流同时汇合的很少见,往往就是两条两条的,而且kettle中,我也还没有见到过有工具是同时针对3个以上的流进行操作的,比如Database lookup,Append Streams,都是针对两个流的。在这里,有点像以前我在Database lookup里见到的差不多,那个所谓的keys,这里一样和我在数据库中见到的不完全一样的性质,在这里它紧紧是代表一种记录的对齐方式,这样的目的,就是避免数据汇合时导致错乱。这些数据汇合之后,到了下一步, ,顾名思义 这里是修改某些字段值的意思我看到下面的代码: 很可惜,在学校时,我专业的会计课只开了一门,这里也应该有会计的思想吧,所谓借贷记账法,这个SUM_AMOUNT是刚才新的字段,是把那些INVOICE_AMOUNT相加的总和,如果为负值,那么就将INVOICE_AMOUNT设为相反数,QUANTITY的值也设为相反数,为了证实一下,刚刚去查找了一下百度中对相反数的定义,百度中说和为0的两个数叫做相反数,0的相反数是0,1的相反数是-1,而-1的相反数就是1,理解了吧。会计中的借贷相等法是一个很好的方法,好像其他国家的会计算账也是采用这个方法。这里因为主要研究分析kettle,不再过多深入。 看下一步, ,由于这里的过程我前面已经很详细的看过,所以现在只是总结一下它这几步总的做了什么,
现在对比一下,看得出,这里那些字段被抛弃了,到这里就把REMARKS和Datatype两个字段给排除了。下面看排序的字段,再看分组
这其中涉及到的字段,尤其是分组的,其实很多,下面ar_customer_mapping 我的老朋友,他又出现了,还记得这是我第1个transform时候创建的,里面就两个字段abbr和fnumber,客户编码系统而已。 这个过滤把这里的数据分成了两部分,为什么要分成两部分呢,也许是方便处理吧。 这里的过滤条件是debit=debit_Note时候, 这个dn_category的性质其实和我上面提到的ar_customer_mapping表的作用性质是一样的,都是提供编码参照的,不同的是这个表并不在transform中创建,而是原来在2.3中就有了的,只要是2.3,ds_erp和k3_HK中有的表,都不是JOB中新创建的,同样只要是在2.25和AR中有的表,都是JOB新创建的表。理解这点,我觉得也很重要。这个dn_category, 参照的字段是cat_code,并且将新的字段dn换成INVOICE_SUBTYPE,其实从这里就可以多少看出,为什么这个tranform的名字叫做dn,说明这里,这一步是这里最为重要的,而这个transform当初产生的主要原因也在此。好了,看到后面部分吧,从现在开始,我要以更快的速度来分析这些内容了,因为后面的部分,几乎都是我前面遇到过的步骤的重复。JS把INVOICE_PAYMENTTERM='DN'字段取值为DN,然后,两个地方的数据汇合 打开INVOICE_TYPE_Mapper, 这个感觉和我以前看到的JS做了一样的事情,但无疑的是values Mapper一般只能针对这种非常规范的数据,而javascrip是可以针对多重条件判断,是树形的都可以的。还记得数据结构中的二叉树吗?记住下面这一部分非常重要的内容,毫无疑问,这些送入到import_temp中的17个字段是必须铭记在心的,这些不但对后面的分析AR数据库非常有帮助,同样对分析前面的有非常重要的参照,前面所做的一切,都是为了获得下面的结果,所以 这6个个transform到这里就基本分析完了,下面总结一下这整个transform都做了些什么:从2.3中输入有关客户和发票的信息,然后经过编码,过滤和分组,最后将数据送入2.252.import中,其实这些和前面分析过的过程是一样的,不同点是这里增加了操作步骤。 7.现在开始,我看第7个transform CN和CDN其实只是相差一个字母,打开这个cdn,数据源同样来自2.3下面是编辑框中的SQL SELECT debit_note_head.debtor AS abbr, debit_note_detail.product AS INVOICE_TYPE, debit_note_detail.dn_cat_code, debit_note_head.dn_no as INVOICE_NO, debit_note_head.remark AS REMARKS, debit_note_detail.currency_code AS INVOICE_CURRENCY, debit_note_detail.job_no AS MO_NO, debit_note_detail.po_no AS PO, debit_note_detail.style_no AS STYLE_NO, debit_note_detail.dn_amt AS INVOICE_AMOUNT, debit_note_head.dn_date AS INVOICE_DATE, debit_note_head.debtor_desc AS FABRIC_NAME FROM debit_note_detail INNER JOIN debit_note_head ON debit_note_detail.dn_no = debit_note_head.dn_no WHERE (debit_note_head.dn_date >= CONVERT(DATETIME, '2011-01-01 00:00:00', 102)) 这里画了黑线的,如果我记住了以前那些字段的话,那么现在对于这些字段应该非常亲切了,从2.3的这些表中,抽取这些字段出来,再和ar_customer_mapping合码,接着看下面的 INVOICE_PAYMENTTERM="CDN"; if (INVOICE_AMOUNT.getNumber()<0) { INVOICE_PAYMENTTERM="CCN"; }
INVOICE_AMOUNT.setValue(-INVOICE_AMOUNT.getNumber()); 如果付款类型为CDN的话,那么就把付款类型改成CCN,且发票金额改成相反数,后面是过滤值之后的 ,这个里面有的内容其实我完全可以不打开看,就是dn_categeory里面的两个字段,CAT_CODE和CDN,随着时间的加长,我应能感觉到,CAT_CODE必须要是刚刚在前面筛选出来在流中有的,这也就再次证明了前面几个内容悟出来的是正确的了。
后面看到select values, 现在打开它,可以看到这里和前面的那个transform还是有差别的,这里只有12个字段,前面那个却有17个,而最后都导入了2.252.import_temp.这点要记住。第7个transform分析完了,现在总结一下这个transform所做的任务: 从2.3中的多个表中筛选数据,然后同客户编码和分类编码合码之后,最后经过分组过滤筛选得到12个字段的数据流,最后将数据导入到import_temp中。 8.现在开始,我看第8个transform
这是这所有的transform中看到的最简单的一个transform了吧,就一个工具 ,顾名思义,更新数据,直接执行SQL语言的,其实几乎kettle里面的所有工具都是通过执行SQL语句而达到目标的,但是他们封装在一起成为一个工具的时候,就是一个函数了,在编辑框中,写入的仅仅是参数而已。理解了这一点,打开这个SQL框,里面往往当然是比较直接的SQL,因为复杂的操作的时候,往往用其它工具更加简单 在这里是仅仅用了更新操作,更新的也仅仅是import_temp中那些类似于bool类型的数据。 好了,这个transform分析完了。 9.现在开始,我看第9个transform
|
| |||
打开这个transform, 很好吧,也就4个非常简单的transform,这个表输入的数据是来自2.252的import_temp,
SELECT INVOICE_NO, CUST_NAME, INVOICE_DUEDATE, INVOICE_CURRENCY, INVOICE_PAYMENTTERM, INVOICE_DEPT, INVOICE_DATE, SALES_BY, REGION
FROM import_temp
WHERE (IMPORT_STATUS >= 0) AND (INVOICE_DATE >= '2011-1-1')
这个也很简洁吧,就从前面的我看过的那些transform中抽取这9个字段的值放入流中,然后以 INVOICE_NO排序和分组 现在分析一下这里了,因为前面并没有在这里进行深入的分析,这个Aggregates到底做什么了呢,这个加入的要求最大值的这些行是怎么取的?取到之后放到了哪里?我想应该会是取字段中的一个聚合,然后放到该字段的最后一条记录上面。现在看到这个表输出了这个是这里新创建的表 ar_import_temp_summary,同样的,这也是一个非常重要的表, 后面的其他transform中一样,我一样会看到它,算起现在,kettle一共创建了那些表呢,应该就是下面三个
ar_custommer_mapping,
import_temp,
ar_import_temp_summary,而且这3个表都是创建在2.252中,也就是说,在这之前还没有和AR数据库打过交道。
到了这里,第9个transform分析完了,从2.3中抽取船务和发票相关的数据,然后再以发票号排序和分组统计,最后导入数据到新创建的表ar_import_temp_summary中。
10.现在开始,我看第10个transform,
,比起前面的来,够简单吧,看表输入中SQL:
SELECT INVOICE_NO, CUST_NAME, INVOICE_DUEDATE, INVOICE_CURRENCY, INVOICE_PAYMENTTERM, INVOICE_DEPT, INVOICE_DATE, SALES_BY, REGION
FROM ar_import_temp_summary
现在是在刚才的基础上,从刚刚新建的那个表中,抽取那些输入的数据,好了看更新
同样的是以INVOICE_NO作为参照字段,将数据流中的数据替换成流中的数据,这样做的目标就是把原来的旧数据全部替换成现在的新数据。这个transform所做的事情,就是把原来的全部的旧数据换成新数据。
11.现在开始,我看第11个transform
打开这个transform, 新朋友AR终于出现了,表输入中的SQL显示,这些都是从AR中的import_temp中筛选那些数据,在温习一下这些字段吧
SELECT INVOICE_NO, CUST_NAME, INVOICE_TYPE, INVOICE_SUBTYPE, INVOICE_AMOUNT, INVOICE_DUEDATE, INVOICE_CURRENCY,
INVOICE_PAYMENTTERM, INVOICE_DEPT, INVOICE_DATE, BUYER, LABEL, DIVISION, SEASON, DILIVERY_DATE, REQ_DATE, CUSTOMER_MR,
GARMENT_NO, STYLE_NO, SALES_BY, REGION, FABRIC_NAME, VATNO_DJ, PO, MO_NO, MR, QTY2, QTY2_UNIT, QUANTITY, QUANTITY_UNIT,
PAYMENT_QTY, FOC_QTY, UNIT_DJ, FOC_AMT, COMMISSION, DISCOUNT, PORT_NAME, REF_PRICE, REF_QUANTITY_UNIT, SAMPLE_TYPE,
LAST_SHIP_DATE, SHIPPED_QTY, REMARKS, PI_PRICE, PI_PRICE_CURRENCY, PI_QTY, PI_QTY_UNIT
FROM import_temp
WHERE INVOICE_DATE>= '2011-01-01' AND (REMARKS <>'更新程序清零' OR REMARKS is null)
从上面的代码中可以看出,这是和清除数据表中原有的数据有关,
下面看到表输出, ,第5个新表出现了,import_temp_ar_hk,千万别把这个和import_temp_summary混淆了。好了,总结一个这个transform所做的工作:
从AR数据库的ar_import_temp中抽取要清除的数据,然后将数据导入到2.252的import_temp-ar_hk中。
12.现在开始,我看第12个transform
打开看出,这里用了两个表输入,打开第一个表输入,看里面的SQL:
SELECT INVOICE_NO, CUST_NAME, INVOICE_TYPE, INVOICE_SUBTYPE, INVOICE_AMOUNT, INVOICE_DUEDATE, INVOICE_CURRENCY,
INVOICE_PAYMENTTERM, INVOICE_DEPT, INVOICE_DATE, BUYER, LABEL, DIVISION, SEASON, DILIVERY_DATE, REQ_DATE, CUSTOMER_MR,
GARMENT_NO, STYLE_NO, SALES_BY, REGION, FABRIC_NAME, VATNO_DJ, PO, MO_NO, MR, QTY2, QTY2_UNIT, QUANTITY, QUANTITY_UNIT,
PAYMENT_QTY, FOC_QTY, UNIT_DJ, FOC_AMT, COMMISSION, DISCOUNT, PORT_NAME, REF_PRICE, REF_QUANTITY_UNIT, SAMPLE_TYPE,
LAST_SHIP_DATE, SHIPPED_QTY, REMARKS, PI_PRICE, PI_PRICE_CURRENCY, PI_QTY, PI_QTY_UNIT,DN_FLAG
FROM import_temp_ar_hk
再打开第二个表输入,里面的SQL如下:
SELECT INVOICE_NO, CUST_NAME, INVOICE_TYPE, INVOICE_SUBTYPE, INVOICE_AMOUNT, INVOICE_DUEDATE, INVOICE_CURRENCY,
INVOICE_PAYMENTTERM, INVOICE_DEPT, INVOICE_DATE, BUYER, LABEL, DIVISION, SEASON, DILIVERY_DATE, REQ_DATE, CUSTOMER_MR,
GARMENT_NO, STYLE_NO, SALES_BY, REGION, FABRIC_NAME, VATNO_DJ, PO, MO_NO, MR, QTY2, QTY2_UNIT, QUANTITY, QUANTITY_UNIT,
PAYMENT_QTY, FOC_QTY, UNIT_DJ, FOC_AMT, COMMISSION, DISCOUNT, PORT_NAME, REF_PRICE, REF_QUANTITY_UNIT, SAMPLE_TYPE,
LAST_SHIP_DATE, SHIPPED_QTY, REMARKS, PI_PRICE, PI_PRICE_CURRENCY, PI_QTY, PI_QTY_UNIT ,DN_FLAG
FROM import_temp
WHERE IMPORT_STATUS >=0 and INVOICE_DATE>='2011-1-1'
我对比着两部分的SQL,不同的地方获取数据源的表,一个是import_temp,一个是import_temp_ar_hk,其中后面这个表是前面的transform创建的,而且当初得到这个表数据条件是
WHERE INVOICE_DATE>= '2011-01-01' AND (REMARKS <>'更新程序清零' OR REMARKS is null)
现在这两个表的数据又合在了一起,看到后面的部分 顾名思义,操作字符串, 很明显,这里是将字段为INVOICE_NO的小写改成大写,也要去除空格,再看后面部分, ,这部分是整个tranform最为重要的部分,合并 ,merge,如果有非常好的直觉,就可以体悟到,merge有点像有人的创伤,慢慢愈合这种感觉,在医学上,这种愈合,最好是自己的肉,因为它有共同的性质,这样相似的地方多,然后经过这些相同的性质的地方,然后再慢慢的长肉,所以这里也是这么一个意思,很相像的,左边的是两个表中都有的字段,后面的部分是需要合并的地方。这种合并不是字段的合并,而是满足左边三个字段相同的情况下,对于的将值合并,在前面分析其他工具的时候,我已经说过,有针对表的,有针对字段的,有针对值的,而这里,也是针对值的一种,好了,看最后一个部分,表输出, ar_merge, 这个表在前面并没有出现过,是这里创建的,我前面还说过,AR中,ds_erp,2.3和k3_hk中所有的表都是原来有的,并没有在这里创建,而2.252和AR中所有的表都是由AR创建的。记住这个ar_merge吧,相当重要。好了,这个transform是将import_temp中的数据和import_temp_hk合并之后输入新创建的表ar_merge中。
13.现在开始,我看第13个transform
打开这个transform. ,里面也仅有一个表输入和一个表输出,看表输入里面的SQL代码:
SELECT INVOICE_NO, FABRIC_NAME, MO_NO, CUST_NAME, INVOICE_TYPE, INVOICE_SUBTYPE, INVOICE_AMOUNT, INVOICE_DUEDATE,
INVOICE_CURRENCY, INVOICE_PAYMENTTERM, INVOICE_DEPT, INVOICE_DATE, BUYER, LABEL, DIVISION, SEASON, DILIVERY_DATE, REQ_DATE,
CUSTOMER_MR, GARMENT_NO, STYLE_NO, SALES_BY, REGION, VATNO_DJ, PO, MR, QTY2, QTY2_UNIT, QUANTITY, QUANTITY_UNIT,
PAYMENT_QTY, FOC_QTY, UNIT_DJ, FOC_AMT, COMMISSION, DISCOUNT, PORT_NAME, REF_PRICE, REF_QUANTITY_UNIT, SAMPLE_TYPE,
LAST_SHIP_DATE, SHIPPED_QTY, REMARKS, PI_PRICE, PI_PRICE_CURRENCY, PI_QTY, PI_QTY_UNIT,DN_FLAG
FROM ar_merge
WHERE (flagfield = 'new')
这是来自2.252为连接的ar_merge里面的数据,这个表是前面那个创建好了的,所以,可以看出,这些transform都是前后之间是要很严密的逻辑顺序的,选取数据的条件是flagfield的值为new,表输出中,是将这些数据输入AR中的import_temp.好了,这个transform分析完了 14.现在开始,我看第14个transform
打开这个transform, ,看到表输入中的SQL
SELECT INVOICE_NO, FABRIC_NAME, MO_NO, CUST_NAME, INVOICE_TYPE, INVOICE_SUBTYPE, INVOICE_AMOUNT, INVOICE_DUEDATE,
INVOICE_CURRENCY, INVOICE_PAYMENTTERM, INVOICE_DEPT, INVOICE_DATE, BUYER, LABEL, DIVISION, SEASON, DILIVERY_DATE, REQ_DATE,
CUSTOMER_MR, GARMENT_NO, STYLE_NO, SALES_BY, REGION, VATNO_DJ, PO, MR, QTY2, QTY2_UNIT, QUANTITY, QUANTITY_UNIT,
PAYMENT_QTY, FOC_QTY, UNIT_DJ, FOC_AMT, COMMISSION, DISCOUNT, PORT_NAME, REF_PRICE, REF_QUANTITY_UNIT, SAMPLE_TYPE,
LAST_SHIP_DATE, SHIPPED_QTY, REMARKS, PI_PRICE, PI_PRICE_CURRENCY, PI_QTY, PI_QTY_UNIT,DN_FLAG
FROM ar_merge
WHERE (flagfield = 'changed')
和上一步几乎差不多, 从这里能看出,这步骤是更新AR数据库中import_temp表的数据,这里重复一下inert/update这个工具里面的内容, 这里的三个字段是更新数据库中数据时候的参照字段,和SQL语句里面的两个表直接的等值连接一样如select c1 from t1,c2 from t2 where t1.c1=t2.c2
而上面部分的三个字段就相当于这里where后面的部分,好了,这个tranform分析完了。
15.现在开始,我看第15个transform
打开这个transform,这里的第一个表输入和前面的完全相同,代码如下
SELECT INVOICE_NO, FABRIC_NAME, MO_NO, CUST_NAME, INVOICE_TYPE, INVOICE_SUBTYPE, INVOICE_AMOUNT, INVOICE_DUEDATE,
INVOICE_CURRENCY, INVOICE_PAYMENTTERM, INVOICE_DEPT, INVOICE_DATE, BUYER, LABEL, DIVISION, SEASON, DILIVERY_DATE, REQ_DATE,
CUSTOMER_MR, GARMENT_NO, STYLE_NO, SALES_BY, REGION, VATNO_DJ, PO, MR, QTY2, QTY2_UNIT, QUANTITY, QUANTITY_UNIT,
PAYMENT_QTY, FOC_QTY, UNIT_DJ, FOC_AMT, COMMISSION, DISCOUNT, PORT_NAME, REF_PRICE, REF_QUANTITY_UNIT, SAMPLE_TYPE,
LAST_SHIP_DATE, SHIPPED_QTY, REMARKS, PI_PRICE, PI_PRICE_CURRENCY, PI_QTY, PI_QTY_UNIT
FROM ar_merge
WHERE (flagfield = 'deleted')
表输出也完全相同,仅仅是多了一个js, 这个 就是和前面的transform不同的地方,是彻底的把这些数据给删除。最后一步的表输入,当然毫无疑问是把空的数据输入到了AR 中的import_temp了。现在分析完了这个tranform,回顾一下这前面3个tranform所做的全部工作:
第一, 将新数据输入AR表,第二,将旧的数据更新,第三,将原来的数据删除。
16.现在开始,我看第16个transform
可以预见,16这个tranform将会特别简单, ,看到表输入里面的内容,现在仔细分析一下
SELECT newentry.INVOICE_NO, CASE WHEN existingentry.INVOICE_NO IS NULL THEN 0 ELSE 2 END AS IMPORT_STATUS
FROM (SELECT INVOICE_NO
FROM import_temp_ar_hk
GROUP BY INVOICE_NO) AS existingentry FULL OUTER JOIN
(SELECT INVOICE_NO
FROM ar_merge
WHERE (flagfield = 'new')
GROUP BY INVOICE_NO) AS newentry ON existingentry.INVOICE_NO = newentry.INVOICE_NO
WHERE (NOT (newentry.INVOICE_NO IS NULL))
UNION
SELECT INVOICE_NO, 2 as IMPORT_STATUS
FROM ar_merge
WHERE (flagfield = 'changed') OR
(flagfield = 'deleted')
GROUP BY INVOICE_NO
虽然这个表输入中的SQL语句很短,但是这段SQL语句极具代表性,因为它涉及到前面讨论过的很多语法问题,这里仅仅是用了两个数据表,一个是import_temp_ar_hk,还有一个是ar_merge,
涉及到的语法有,outer join,union,case when then end as, groub by等。
现在,来讨论这段SQL语句里面的逻辑结构,首先,从Import_temp和ar_merge中筛选INVOICE_NO字段的数据,组成的新表分别命名为别名exitstingentry和newentry,,再将其所拥有的数据值抽取出来,去除空值,然后,从ar_merger中将所有INVOICE_NO的值抽取出来,组成新的数据表,最后从这个数据表中抽取INVOICE_NO,如果这个INVOICE_NO为空值,则将其导入状态值设为0,如果不为空值,将其导入状态设为2。下面看, ,无需怀疑,这里就涉及前面两个字段,将AR 中import_temp的导入状态更改。
17.现在开始,我看第17个transform
好不容易弄好了,不知道按了那个键,突然卡住了,晕死,现在这个transform又要重新开始写了。这个transform里面有两个表输入,一个为从K3_HK中抽取一个字段PaymentTerm,一个为从AR中的pary_type表中抽取字段。现在看SELECT MAX(CONVERT(int, substring(Paytypeid,4,5))) AS Expr1
FROM paytype这个是第一个表输入中的代码,这里是选取这个列中的最大值,第4未开始的5个数。看下面的第二个表输入中的代码
select distinct PaymentTerm,? as ser from(
Select
substring(t.fnumber, 1,1)+substring(t.fnumber, 4,1)+ substring(t.fnumber, 6,4) as abbr,LTRIM(RTRIM(t.FName)) as CustName,LTRIM(RTRIM(t.FAddress)) as FAddress,LTRIM(RTRIM(t.FPhone)) as FPhone,LTRIM(RTRIM(t.Ffax))as Ffax,
LTRIM(RTRIM(o.FName)) as Fname1,LTRIM(RTRIM(t.FContact)) as FContact,LTRIM(RTRIM(v.FName)) as Fname2,LTRIM(RTRIM(t.FShortName)) as FShortName,t.fnumber
,substring(t.fnumber, 1,4) as CityID,t.Fcorperate, o.FName AS PaymentTerm, e.FName AS EmpName
from AIS20040902164905.dbo.t_organization t
left join
AIS20040902164905.dbo.t_Emp e ON t.Femployee = e.FItemID LEFT OUTER JOIN
AIS20040902164905.dbo.t_settle o
on t.FsetID=o.FitemID
left join AIS20040902164905.dbo.t_submessage v
on t.FRegionID=v.FInterID
where t.FNumber like 'B%'
union
Select
substring(t2.fnumber, 3,2)+ substring(t2.fnumber, 6,4) as abbr,LTRIM(RTRIM(t2.FName)) as CustName,LTRIM(RTRIM(t2.FAddress)) as FAddress,LTRIM(RTRIM(t2.FPhone)) as FPhone,LTRIM(RTRIM(t2.Ffax))as Ffax,
LTRIM(RTRIM(o2.FName)) as Fname1,LTRIM(RTRIM(t2.FContact)) as FContact,LTRIM(RTRIM(v2.FName)) as Fname2,LTRIM(RTRIM(t2.FShortName)) as FShortName,t2.fnumber
,substring(t2.fnumber, 1,4) as CityID,t2.Fcorperate, o2.FName AS PaymentTerm, e2.FName AS EmpName
from AIS20041216164951.dbo.t_organization t2
left join
AIS20041216164951.dbo.t_Emp e2 ON t2.Femployee = e2.FItemID LEFT OUTER JOIN
AIS20041216164951.dbo.t_settle o2
on t2.FsetID=o2.FitemID
left join AIS20041216164951.dbo.t_submessage v2
on t2.FRegionID=v2.FInterID
where t2.FNumber like 'C%') as emp where EmpName<>'' and EmpName is not null
当分析SQL代码的时候,按照这种分层的方法,可能会更好些,这里可谓是同时涉及到多个数据库多个表的查询。不过,最终查出的字段就是PaymentTerm,现在,开始进入下一步 ,这个太熟悉不过了,看里面查询的是AR中的pay_type表中的paytype_id 并将其重新命名为id
现在看下一步, ,AR中第一次使用序列,序列是什么呢?就有点像是数据库中的等差数列,就是增加了一个字段,这字段的值是随着记录的增多,自动增长的,至于作用,到了后面用到这个id的时候,再分解。后面 ,是用来计算的工具,计算的内容,
就是把前面的ser字段+前面序列生成的valuename,然后变成新的字段sequence为名的新字段。看到接下来的 ,添加字段,里面是 这里是把sequence<10的时候,将新添加的字段zerop值设为0.后面的 select values筛选的是sequence字段, 这是第二个 ,里面是
这里的PM-是一个字符串,这里的zerop是上次添加的字段,这里的意思是添加一个新字段Paytypeid,其值为PM-这个字符串加上zerop这个字符串加上sequence这个字符串的结果。最后看到
插入更新数据库, 是参照字段,需要更新的字段是 paytype,
和paytypeid,分别更新成为流中的paymentTerm和paytypeid中的值,再次申明,这里是针对字段值而非字段而言的,所以是更新的值。
好了这个tranform分析完了,下面总体分析一下这个tranform所做的工作:
通过查询AR的pay_type及其K3_HK的两个数据库中的多个表所得到的两个字段paytype和paymenTerm两个字段,再更新AR中的paytype表中的相应字段。
18.现在开始,我看第18个transform
打开这个emp,如图所示,和刚才的一模一样的结构
在这里,按照上面的编号,1的表输入是从AR中的personnel中抽取personnelID,而前面那个transform是从paytype中抽取pertype_id,所以是换汤不换药
SELECT MAX(CONVERT(int, PersonnelID)) AS Expr1
FROM Personnel
而后面的这个表输入,也仅仅是换了名字
select distinct EmpName,? as ser from(
Select
substring(t.fnumber, 1,1)+substring(t.fnumber, 4,1)+ substring(t.fnumber, 6,4) as abbr,LTRIM(RTRIM(t.FName)) as CustName,LTRIM(RTRIM(t.FAddress)) as FAddress,LTRIM(RTRIM(t.FPhone)) as FPhone,LTRIM(RTRIM(t.Ffax))as Ffax,
LTRIM(RTRIM(o.FName)) as Fname1,LTRIM(RTRIM(t.FContact)) as FContact,LTRIM(RTRIM(v.FName)) as Fname2,LTRIM(RTRIM(t.FShortName)) as FShortName,t.fnumber
,substring(t.fnumber, 1,4) as CityID,t.Fcorperate, o.FName AS PaymentTerm, e.FName AS EmpName
from AIS20040902164905.dbo.t_organization t
left join
AIS20040902164905.dbo.t_Emp e ON t.Femployee = e.FItemID LEFT OUTER JOIN
AIS20040902164905.dbo.t_settle o
on t.FsetID=o.FitemID
left join AIS20040902164905.dbo.t_submessage v
on t.FRegionID=v.FInterID
where t.FNumber like 'B%'
union
Select
substring(t2.fnumber, 3,2)+ substring(t2.fnumber, 6,4) as abbr,LTRIM(RTRIM(t2.FName)) as CustName,LTRIM(RTRIM(t2.FAddress)) as FAddress,LTRIM(RTRIM(t2.FPhone)) as FPhone,LTRIM(RTRIM(t2.Ffax))as Ffax,
LTRIM(RTRIM(o2.FName)) as Fname1,LTRIM(RTRIM(t2.FContact)) as FContact,LTRIM(RTRIM(v2.FName)) as Fname2,LTRIM(RTRIM(t2.FShortName)) as FShortName,t2.fnumber
,substring(t2.fnumber, 1,4) as CityID,t2.Fcorperate, o2.FName AS PaymentTerm, e2.FName AS EmpName
from AIS20041216164951.dbo.t_organization t2
left join
AIS20041216164951.dbo.t_Emp e2 ON t2.Femployee = e2.FItemID LEFT OUTER JOIN
AIS20041216164951.dbo.t_settle o2
on t2.FsetID=o2.FitemID
left join AIS20041216164951.dbo.t_submessage v2
on t2.FRegionID=v2.FInterID
where t2.FNumber like 'C%') as emp where EmpName<>'' and EmpName is not null
后面的分别是参照 表中的Name,然后添加 然后将表中PernnelID中的值添加到这里,改字段名为id,后面的 ,里面为
zerop='';
if (sequence<100)
{
zerop='0';
}
if (sequence<10)
{
zerop='00';
}
和前面稍微有点点不同就是添加了一层,sequence<100.
PersonnelID=zerop+trim(sequence);
这个地方和前面的不同点是没有加字符串’PM-’.最后看 ,
更新的是AR中的Personnel表,以字段Name为参照,以流中的EmpName和PersonnelID替换表中的Name和PersonnelID的值
19.现在开始,我开第19个transform
打开这个tranform,这个是最后一个比较复杂的transform了,而且这个transform是在前面那两个transform的基础上,才能运行的,看到这个表输入中的代码
Select
substring(t.fnumber, 1,1)+substring(t.fnumber, 4,1)+ substring(t.fnumber, 6,4) as abbr,LTRIM(RTRIM(t.FName)) as CustName,LTRIM(RTRIM(t.FAddress)) as FAddress,LTRIM(RTRIM(t.FPhone)) as FPhone,LTRIM(RTRIM(t.Ffax))as Ffax,
LTRIM(RTRIM(o.FName)) as Fname1,LTRIM(RTRIM(t.FContact)) as FContact,LTRIM(RTRIM(v.FName)) as Fname2,LTRIM(RTRIM(t.FShortName)) as FShortName,t.fnumber
,substring(t.fnumber, 1,4) as CityID,t.Fcorperate, o.FName AS PaymentTerm, e.FName AS EmpName
from AIS20040902164905.dbo.t_organization t
left join
AIS20040902164905.dbo.t_Emp e ON t.Femployee = e.FItemID LEFT OUTER JOIN
AIS20040902164905.dbo.t_settle o
on t.FsetID=o.FitemID
left join AIS20040902164905.dbo.t_submessage v
on t.FRegionID=v.FInterID
where t.FNumber like 'B%'
union
Select
substring(t2.fnumber, 3,2)+ substring(t2.fnumber, 6,4) as abbr,LTRIM(RTRIM(t2.FName)) as CustName,LTRIM(RTRIM(t2.FAddress)) as FAddress,LTRIM(RTRIM(t2.FPhone)) as FPhone,LTRIM(RTRIM(t2.Ffax))as Ffax,
LTRIM(RTRIM(o2.FName)) as Fname1,LTRIM(RTRIM(t2.FContact)) as FContact,LTRIM(RTRIM(v2.FName)) as Fname2,LTRIM(RTRIM(t2.FShortName)) as FShortName,t2.fnumber
,substring(t2.fnumber, 1,4) as CityID,t2.Fcorperate, o2.FName AS PaymentTerm, e2.FName AS EmpName
from AIS20041216164951.dbo.t_organization t2
left join
AIS20041216164951.dbo.t_Emp e2 ON t2.Femployee = e2.FItemID LEFT OUTER JOIN
AIS20041216164951.dbo.t_settle o2
on t2.FsetID=o2.FitemID
left join AIS20041216164951.dbo.t_submessage v2
on t2.FRegionID=v2.FInterID
where t2.FNumber like 'C%';
这里分成上下两部分,上面部分是从AIS20040902164905,数据库中抽取数据,下面部分是从AIS20041216164951中抽取数据,所以看着段眼花缭乱的代码的时候,先把代码分开,不论是多么复杂的查询,都是一部分一部分,非常有条理的,而且越是长的代码,这种逻辑就越清晰。多的只是数据库,表,字段,连接而已。现在回顾一下LEFT OUTER JOIN,和LEFT JOIN的区别,前面这个是左表中的所有字段加上右表中在左表中没有的字段,而那些左表中有的字段就不需要,而后面的相反,是左表中有的字段加上右表中在左表中都有的字段的值。
这个表输入,是从以K3_HK为连接的两个数据库中导入客户相关资料,
筛选了如做截图中的15个字段,并对funumber和CustName进行了重新命名为Notes和full_name, 这个是用来添加字段的,上面部分的,添加了
Cust_Name=CustName.getString();
Eng_Name=CustName.getString();
Cust_Name=trim(Cust_Name);
Eng_Name=trim(Eng_Name);
if (!(/^[^\u4e00-\u9fa5]+$/.test(Cust_Name)) )
{
Eng_Name=null;
}
Cust_Name和Eng_Name两个字段,他们取值的来源为客户关系中的Cust_Name.另外一个代码如下
Cust_Name =CustName.getString().substr(CustName.getString().indexOf("<"),CustName.getString().indexOf(">"));
Cust_Name= Cust_Name.replace(">","");
Cust_Name= Cust_Name.replace("<","");
Eng_Name=CustName.getString().substr(0,CustName.getString().indexOf("<"));
Eng_Name=trim(Eng_Name);
Cust_Name=trim(Cust_Name);
上面代码的意思是添加两个字段Cust_Name和Eng_Name,并且在从Cust_Name获取值得基础上,加上“<” 和“>”。
再看后面这一段复杂点的 ,这个JS并没有添加字段了,
function transCol2ToCol1(col, num)
{
var trimedcol2;
var col2length;
if(col==null||trim(col)==" "||trim(col)=="")
{
return " ";
}
trimedcol2=trim(col.replaceAll("[^\x00-\xff]","11"));
col2length=trimedcol2.length;
var ch,bytenum=0;
var rs = "";
var pt = /[^\x00-\xff]/;
for (var i=0; i < num; i++)
{
ch = col.substr(i, 1);
if (ch.match(pt))
{
bytenum += 2;
if (bytenum > num)
{
return rs;
}
}
else{
bytenum += 1;
}
rs += ch;
if (bytenum == num){
return rs;
}
}
return rs;
}
Cust_Name.setValue(transCol2ToCol1(Cust_Name.getString(),60));
if (Eng_Name.getString()==null||Eng_Name.getString()==""){
Eng_Name.setValue(Cust_Name.getString());
}
Eng_Name.setValue(transCol2ToCol1(Eng_Name.getString(),100));
上面这个函数在名船务系统发票的那编号为2的transform中已经写过了,至于这里整个entry的作用,就是将新建的字段顺序更换。
看后面的 ,其中选取了流中的15个字段,显然,有些字段过滤掉了,划线的是新添加的字段
看后面的 ,里面是参照AR中的Personne表中的 Name字段,对应于流中的EmpName字段,添加了Personnel表中的Personnel表中的 PersonnelID字段,后面的
添加的是AR中paytype表中的PaytypeId字段,参照的是paytype字段。最后一个entry, 用流中 的字段更新数据表中原有的字段和字段取值。这个表为AR里面的customer表。好了,现在,回顾一下这整个transform所做的任务:开始,表输入从K3_HK中抽取有关客户的字段和数据,然后过滤掉那些无效数据,生成两个新字段,再分别从AR数据库中的customer表和Personnel选出两个字段,最后将数据表创建在AR上名为customer.
20.现在开始,看第20个tranform
从K3导入供应商这个tranform,里面并没有前面那个tranform涉及到那么复杂 ,一个表输入,一个数据输出
先看表输入里面的代码
SELECT FItemID, FAddress, FCity, FProvince, FCountry, FPostalCode, FPhone, FFax, FEmail, FHomePage, FCreditLimit, FTaxID, FBank, FAccount, FBrNo, FBoundAttr,
FErpClsID, FShortName, FPriorityID, FPOGroupID, FStatus, FLanguageID, FRegionID, FTrade, FMinPOValue, FMaxDebitDate, FLegalPerson, FContact, FContactAcct,
FPhoneAcct, FFaxAcct, FZipAcct, FEmailAcct, FAddrAcct, FTax, FCyID, FSetID, FSetDLineID, FTaxNum, FPriceClsID, FOperID, FCIQNumber, FDeleted, FSaleMode,
FName, FNumber, FParentID, FShortNumber, FARAccountID, FAPAccountID, FpreAcctID, FlastTradeAmount, FLastRPAmount, FFavorPolicy, Fdepartment, Femployee,
Fcorperate, FBeginTradeDate, FEndTradeDate, FLastTradeDate, FLastReceiveDate, FcashDiscount, FcurrencyID, FMaxDealAmount, FMinForeReceiveRate,
FMinReserveRate, FMaxForePayAmount, FMaxForePayRate, FdebtLevel, FCreditDays, FValueAddRate, FPayTaxAcctID, FModifyTime, F_102
FROM t_Supplier
WHERE (FDeleted = 0)
容易看出来,这是从t_Supplies中抽取那些没有标记为删除的数据。从这里将数据抽取出来之后,是抽取了流中的如下数据然后送入到AR中provider表中
这个transform就是从k3中的供应商里面的表里的数据抽取到AR数据库中的provider表中。
21.现在开始,我看第21个tranform
打开这个tranform,里面有两个表输入
这第一个表输输入里面是从2.252的import_temp_ar_hk中抽取INVOICE_NO和INVOICE_AMOUNT总和,
SELECT INVOICE_NO, SUM(INVOICE_AMOUNT) AS SUM_AMOUNT
FROM import_temp_ar_hk
GROUP BY INVOICE_NO
第二个表输入是从2.252的import_temp中抽取INVOICE_NO和INVOICE_AMOUNT总和
SELECT INVOICE_NO, SUM(INVOICE_AMOUNT) AS SUM_AMOUNT
FROM import_temp
WHERE IMPORT_STATUS >=0 and INVOICE_DATE>='2011-1-1'
GROUP BY INVOICE_NO
后面的 是将INVOICE_NO中所有英文字符变成大写, 将INVOICE_NO以升序排列,并且通过 将两个据流中的数据合并
最后将数据送入到2.252的ar_merge_sum表中,这是一个新建的表。
22.现在开始,我看第22个transform
因为这个transform涉及到的内容实在是太少了,是从刚才那个
ar_merger_sum中抽取INVOICE_NO字段,然后将AR中和这个INVOICE_NO相同的删除。
SELECT INVOICE_NO
FROM ar_merge_sum
23.现在开始,看第23个transform
这是ar_job中的最后一个transform了,里面只有一个表输入和一个表输出,
SELECT INVOICE_NO, FABRIC_NAME, MO_NO, CUST_NAME, INVOICE_TYPE, INVOICE_SUBTYPE, INVOICE_AMOUNT, INVOICE_DUEDATE,
INVOICE_CURRENCY, INVOICE_PAYMENTTERM, INVOICE_DEPT, INVOICE_DATE, BUYER, LABEL, DIVISION, SEASON, DILIVERY_DATE, REQ_DATE,
CUSTOMER_MR, GARMENT_NO, STYLE_NO, SALES_BY, REGION, VATNO_DJ, PO, MR, QTY2, QTY2_UNIT, QUANTITY, QUANTITY_UNIT,
PAYMENT_QTY, FOC_QTY, UNIT_DJ, FOC_AMT, COMMISSION, DISCOUNT, PORT_NAME, REF_PRICE, REF_QUANTITY_UNIT, SAMPLE_TYPE,
LAST_SHIP_DATE, SHIPPED_QTY, REMARKS, PI_PRICE, PI_PRICE_CURRENCY, PI_QTY, PI_QTY_UNIT,2 as IMPORT_STATUS
FROM import_temp
WHERE INVOICE_NO in(SELECT INVOICE_NO FROM ar_merge_sum)
表输入是将2.252中import_temp中的数据输入到流中
表输出是将表输入的数据输入到AR中的Import_temp,这样,所有的工作都完成了。到这里ar_job就完成了。
24.现在开始,看第24个transform
这里是ar_datacompare_job的开始,这里的前提条件是要前面的ar_job正常执行完所有transform之后,才能执行的。现在打开ar_xls,
这是11个excels表的数据经过筛选合并到2.252中的ar_xls_export_pre
表中的过程,这些excel可能是会计过程中计算出来的excel表。
因为涉及到的excel表有点多,但是各个excel到达终表的过程中的处理是一样的,这里最终筛选出来的字段就只有四个,INVOICE_DATE,INVOICE_NO,INVOICE_AMOUNT,INVOICE_CURRENCY.
25.现在开始,看第25个transform
这个transform也很简单,一个表输入和一个表输出,是在前面的transform的基础上,进行数据筛选
SELECT invoice_no, CONVERT (datetime,CAST ( DATEPART(dd,xls.invoicedate) AS varchar) +'/'+
CAST ( DATEPART(mm,xls.invoicedate) AS varchar) +'/'+
CAST ( DATEPART(yyyy,xls.invoicedate) AS varchar) ,103) as invoice_date
, invoice_amount,invoice_currency
FROM
(SELECT [invoice_no]
,[invoice_date]
,CAST ( [invoice_date] AS datetime ) as [invoicedate]
,[invoice_amount]
,[invoice_currency]
FROM [ar_xls_export_pre]
where [invoice_no] not like 'H%'
union all
SELECT [invoice_no]
,[invoice_date]
,CONVERT (datetime, [invoice_date] ,103) as [invoicedate]
,[invoice_amount]
,[invoice_currency]
FROM [ar_xls_export_pre]
where [invoice_no] like 'H%')
as xls
将上一个transform中产生的ar_xls_export_pre表中的数据输入到另外一个叫做2.252的ar_xls_export表中。
26. 现在开始,看第26个transform
这是这个AR中最后一个transform了,
下面是这个表输入中的SQL
SELECT CONVERT (datetime,CAST ( DATEPART(dd,FillDate) AS varchar) +'/'+
CAST ( DATEPART(mm,FillDate) AS varchar) +'/'+
CAST ( DATEPART(yyyy,FillDate) AS varchar) ,103) as invoice_date1, INVOICE_NO, Currencyid, currtotal
FROM invoice_out
这里面从AR的invoice_out表中共筛选了invoice_date1, INVOICE_NO, Currencyid, currtotal四个字段,参照的字段是是AR中Currentid字段 加入的是 currencynm字段,最后将数据放入到了2.252的INVOICE_OUT中。
转载于:https://www.cnblogs.com/canyangfeixue/archive/2013/01/18/2866080.html
本文链接:https://my.lmcjl.com/post/6029.html
4 评论