我从一个部门的csv文件中收到信息,与不同部门的相同信息进行比较,以检查是否存在差异(每行约44个列中约有3/4行数据)。在表格中有数据之后,我有一个程序可以获取数据并根据总部发送报告。我觉得我这样做的方式不是最有效的。我正在使用oracle进行比较。
这就是我所拥有的:
我有一个vb.net程序解析数据并将其插入提取表
我运行一个程序,将两个表上的完全外连接转换为一个新表,其中一个部门中的字段以“_c”为前缀
我运行另一个程序来比较旧/新数据,并使用详细信息和摘要信息更新2个不同的表。以下是程序内部的代码:
DECLARE
CURSOR Cur_Comp IS SELECT * FROM T.AEC_CIS_COMP;
BEGIN
FOR compRow in Cur_Comp LOOP
--If service pipe exists in CIS but not in FM and the service pipe has status of retired in CIS, ignore the variance
If(compRow.pipe_num = '' AND cis_status_c = 'R')
continue
END IF
--If there is not a summary record for this HQ in the table for this run, create one
INSERT INTO t.AEC_CIS_SUM (HQ, RUN_DATE)
SELECT compRow.HQ, to_date(sysdate, 'DD/MM/YYYY') from dual WHERE NOT EXISTS
(SELECT null FROM t.AEC_CIS_SUM WHERE HQ = compRow.HQ AND RUN_DATE = to_date(sysdate, 'DD/MM/YYYY'))
-- Check fields and update the tables accordingly
If (compRow.cis_loop <> compRow.cis_loop_c) Then
--Insert information into the details table
INSERT INTO T.AEC_CIS_DET( Fac_id, Pipe_Num, Hq, Address, AutoUpdatedFl,
DateTime, Changed_Field, CIS_Value, FM_Value)
VALUES(compRow.Fac_ID, compRow.Pipe_Num, compRow.Hq, compRow.Street_Num || ' ' || compRow.Street_Name,
'Y', sysdate, 'Cis_Loop', compRow.cis_loop, compRow.cis_loop_c);
-- Update information into the summary table
UPDATE AEC_CIS_SUM
SET cis_loop = cis_loop + 1
WHERE Hq = compRow.Hq
AND Run_Date = to_date(sysdate, 'DD/MM/YYYY')
End If;
END LOOP;
END;
对于表格的所有44列,更简单的方法而不是if语句的任何建议? (如果重要的话,每周运行一次)
更新:为了澄清,有88列数据(44个重复项与一个后缀为_c的重复项)。一个表列出了一行中不同的每个字段,因此一行可以表示在该表中写入的30多个记录。另一张表记录了每周的差异数量。
答案 0 :(得分:2)
首先,我相信您的任务可以使用staight SQL实现(并且应该实际)。没有花哨的游标,没有循环,只是选择,插入和更新。我会先解开你的源数据(你不清楚你是否有主键加入两套,我猜你这样做了):
Col0_PK Col1 Col2 Col3 Col4
----------------------------------------
Row1_val A B C D
Row2_val E F G H
以上是您的源数据。使用UNPIVOT
clause我们将其转换为:
Col0_PK Col_Name Col_Value
------------------------------
Row1_val Col1 A
Row1_val Col2 B
Row1_val Col3 C
Row1_val Col4 D
Row2_val Col1 E
Row2_val Col2 F
Row2_val Col3 G
Row2_val Col4 H
我想你明白了。假设我们有一组带有一组数据的table1和带有第二组数据的相同结构化table2。最好使用索引组织表。
下一步是将行相互比较并存储差异细节。类似的东西:
insert into diff_details(some_service_info_columns_here)
select some_service_info_columns_here_along_with_data_difference
from table1 t1 inner join table2 t2
on t1.Col0_PK = t2.Col0_PK
and t1.Col_name = t2.Col_name
and nvl(t1.Col_value, 'Dummy1') <> nvl(t2.Col_value, 'Dummy2');
在最后一步,我们更新差异汇总表:
insert into diff_summary(summary_columns_here)
select diff_row_id, count(*) as diff_count
from diff_details
group by diff_row_id;
只是粗略的草稿来展示我的方法,我确信还有更多的细节应该被考虑在内。总结一下,我建议两件事:
UNPIVOT
数据SQL
语句代替游标答案 1 :(得分:0)
您的代码中有几个问题:
If(compRow.pipe_num = '' AND cis_status_c = 'R')
continue
END IF
未声明“cis_status_c”。它是AEC_CIS_COMP中的变量还是列?
如果它是一列,只需将条件放入光标,即SELECT * FROM T.AEC_CIS_COMP WHERE not (compRow.pipe_num = '' AND cis_status_c = 'R')
to_date(sysdate, 'DD/MM/YYYY')
这是胡说八道,您将日期转换为日期,只需使用TRUNC(SYSDATE)
无论如何,我认为您可以使用三个单个语句而不是游标:
INSERT INTO t.AEC_CIS_SUM (HQ, RUN_DATE)
SELECT comp.HQ, trunc(sysdate)
from AEC_CIS_COMP comp
WHERE NOT EXISTS
(SELECT null FROM t.AEC_CIS_SUM WHERE HQ = comp.HQ AND RUN_DATE = trunc(sysdate));
INSERT INTO T.AEC_CIS_DET( Fac_id, Pipe_Num, Hq, Address, AutoUpdatedFl, DateTime, Changed_Field, CIS_Value, FM_Value)
select comp.Fac_ID, comp.Pipe_Num, comp.Hq, comp.Street_Num || ' ' || comp.Street_Name, 'Y', sysdate, 'Cis_Loop', comp.cis_loop, comp.cis_loop_c
from T.AEC_CIS_COMP comp
where comp.cis_loop <> comp.cis_loop_c;
UPDATE AEC_CIS_SUM
SET cis_loop = cis_loop + 1
WHERE Hq IN (Select Hq from T.AEC_CIS_COMP)
AND trunc(Run_Date) = trunc(sysdate);
他们没有经过测试,但他们应该给你一个如何做的提示。