遍历 table 的列值

Loop through column values of table

我是 PL-SQL 的新手。我有一个 table,其中包含数千条文件信息记录(摘录如下所示)。我需要比较 2 个文件 A 和 B,对于同一任务,检查 task_name 是否相同或不同.例如,在下面的 table 中,文件 A 任务 10 与文件 B 任务 10 具有相同的 task_name (xx)。而文件 A 任务 20 与文件 B 任务 20 具有不同的 task_name .我应该能够标记出这些差异和相似之处。我想在游标内使用游标来循环和比较这些值,但我不知道如何去做。我目前正在使用 Oracle 11。谢谢

File  Task  Task_name 
A     10    xx         
A     20    xy         
A     30    xz         
B     10    xx         
B     20    xz         

**编辑

感谢您的回复。我需要循环的原因是因为最后我需要显示结果 在以下格式的 clob 变量中。所以我需要在迭代中捕获任务编号和任务名称 在 clob 变量中显示

------文件比较------

不同Task_name

任务 20:文件 A Task_name xx 与文件 B Task_name xz

任务 30:文件 A Task_name xz 对比文件 B Task_name NULL

相同Task_name

任务 10:Task_namexx

您不需要使用 PL/SQL,而是使用 SQL 和 COUNT(..) OVER (..) 分析函数,通过使用 TaskTask_name 列分组 PARTITION BY 子句连同 CASE..WHEN 条件表达式就足够了,例如

SELECT f.*, 
       CASE WHEN COUNT(DISTINCT "File") OVER (PARTITION BY Task, Task_name) = 2 THEN
                 'Same'
            ELSE CASE WHEN COUNT(DISTINCT "File") OVER (PARTITION BY Task) = 1 THEN
                 'Unique'
                 ELSE
                 'Different'
                 END
             END AS flag
  FROM files f

Demo

您也可以使用 operator EXISTS。EXISTS 运算符与子查询一起使用以测试行是否存在。

尽管在您的问题中没有提及 A/B 内的重复项,您可以使用通用查询在 相同组或不同 /

中查找重复项

还要注意这个查询return在只在一个文件组内重复的情况下的正确结果(例如,只在A中) :

   --using cte to set row's number
   with cte as
    (
      select *, row_number()over (order by Task,TaskName)num from Table 
    )
    
       select File,Task,TaskName,
       case
       --using t1.num<>t2.num because current row can refer to itself
        when exists (select 1 from cte t1 where t1.Task=t2.Task and 
          t1.Taskname=t2.TaskName and t1.num<>t2.num) 
        then 'Duplicate'
        else 
         'No Duplicate'
        end as flag 
        from cte t2

如果在您的table中一个文件组中没有重复项,并且您只需要查找 A 和 B 文件组之间的差异,那么可以使用此查询:

           select File,Task,TaskName,
           case
            when exists (select 1 from Table t1 where t1.Task=t2.Task and 
             t1.Taskname=t2.TaskName and t1.File<>t2.File) 
            then 'Duplicate'
            else 
             'No Duplicate'
            end as flag 
            from Table t2
  

您可以使用window function count 对文件group.But 中的Task、TaskName 进行计数,首先您需要删除每个组中的重复项,然后像在一个组中一样对值进行计数。 如果您需要比较 2 个文件 A 和 B,那么您可以尝试这个查询:

Select File, Task,TaskNane,case when countVal>1 then 'Duplicate' else 'No 
 Duplicate' and as flag
        From
     (
      Select count(*)over (partition by file_gr, Task, TaskName) countVal 
      From
       (
        --add new accessorial column as if there's one group
       Select *,  case when File='B' then 'A' else 'A' end as file_gr
       From
          (
          --remove duplicate within each group A and B
           Select distinct File, Task, TaskName from Table
          ) X
       ) Y
   ) Z
with t (Files,  Task,  Task_name ) as
( 
    select 'A',10,'xx' from dual union all
    select 'A',20,'xy' from dual union all
    select 'A',30,'xz' from dual union all
    select 'B',10,'xx' from dual union all
    select 'B',20,'xz' from dual
)
select  t1.*, nvl((select 'Y' from t t2 where t2.files <> t1.files and t2.task = t1.task and t2.task_name = t1.task_name),'N') as is_same
from    t t1
order   by 1, 2

输出:

您可以按任务汇总以获得差异:

select
  task,
  max(case when file = 'A' then task_name end) as task_file_a,
  max(case when file = 'B' then task_name end) as task_file_b
from mytable
where file in ('A', 'B')
group by task
having count(*) <> 2 or count(distinct task_name) <> 1
order by task;

您可以在 PL/SQL 中使用它和 Cursor FOR LOOP。这是草稿:

create or replace function get_diff return clob is
  v_clob clob;
begin
  for row in
  (
    select
      task,
      max(case when file = 'A' then task_name end) as task_file_a,
      max(case when file = 'B' then task_name end) as task_file_b,
      case when count(*) <> 2 or count(distinct task_name) <> 1 
        then 'diff'
        else 'same'
      end as diff_same
    from mytable
    where file in ('A', 'B')
    group by task
    order by diff_same, task
  ) loop
    v_clob := v_clob + ...
  end loop;
end;

您可以像这样访问行数据:'Task for file A is' || row.task_file_a.

您必须检查相同/差异,或者您只需使用两个循环,一个用于差异,一个用于相等。