【问题标题】:SQL question using Cursor - case study on taking First Transaction使用 Cursor 的 SQL 问题 - 进行第一次交易的案例研究
【发布时间】:2020-10-29 07:26:44
【问题描述】:

最近,我正在研究 SQL。

我有一个基本但模棱两可的问题如下: 给定一个表A,其中包括交易信息,如交易编号(TRX_NO)、客户名称(CUS_NAME)、客户代码(CUS_CODE)和交易时间(TRX_TIME)。注意,对于每一笔交易,都会有记录。比如Mary在20201024、20201025、20201031去店里,那么这个表里有3条记录。

考虑到这一点,如果使用 temp_table 或 cursor,我如何将所有首次数据插入另一个表 B?

更具体的例子,如果当前表A存储了Mary的3条记录,那么表B应该保存20201024的记录。我该如何实现呢?

我尝试过使用光标,但似乎不是一个好的尝试:

  DECLARE var_VIP   VARCHAR2(20);
        
        CURSOR cur_FIRST IS 
                SELECT A.CUS_CODE 
                FROM TABLEA A
                ORDER BY CUS_CODE, TRX_DATE, TRX_TIME;
                
        --OPEN AND START CURSOR
        BEGIN
        OPEN cur_FIRST;
        LOOP
        FETCH cur_FIRST INTO var_VIP;      
        EXIT WHEN cur_FIRST%NOTFOUND;
              INSERT INTO TABLEB B
              (SELECT* 
              FROM TABLEA A
              ORDER BY TRX_DATE, TRX_TIME);
        END LOOP;
        CLOSE cur_FIRST;

非常感谢您的帮助!!!

【问题讨论】:

  • 您的 DBMS 是 Oracle 还是 SQL Server?语法建议使用第二个。
  • @BarbarosÖzhan 哦,对不起,我没认出来。我正在使用 PL/SQL 开发人员
  • PL/SQL 开发者用于连接 MySQL?
  • 您删除了标签oracle,但没有标记相关的DBMS。
  • @BarbarosÖzhan 哦,我明白了。我对 SQL 世界很陌生......但是,感谢所有提醒和分享您的知识

标签: oracle plsql cursor


【解决方案1】:

我写了一个简短的例子来帮助你理解这个概念。

   --create the tables
    CREATE TABLE TABLEA (CUS_CODE INTEGER,
                         TRX_DATE DATE);
    
    
    CREATE TABLE TABLEB (CUS_CODE INTEGER,
                         TRX_DATE DATE);
    
    --insert some values
    insert into TABLEA values (1, SYSDATE);
    insert into TABLEA values (1, SYSDATE+1);
    insert into TABLEA values (1, SYSDATE+2);
    
    insert into TABLEA values (2, SYSDATE);
    insert into TABLEA values (2, SYSDATE+1);
    insert into TABLEA values (3, SYSDATE+2);

程序代码:

  DECLARE
        CURSOR cur_FIRST IS 
                SELECT A.CUS_CODE, min(A.TRX_DATE) as TRX_DATE
                FROM TABLEA A
                GROUP BY CUS_CODE;
         
         var_VIP  cur_FIRST%rowtype;      
        --OPEN AND START CURSOR
    BEGIN
        OPEN cur_FIRST;
        LOOP
          FETCH cur_FIRST INTO var_VIP;      
          EXIT WHEN cur_FIRST%NOTFOUND;
              INSERT INTO TABLEB VALUES (VAR_vip.CUS_CODE, VAR_VIP.TRX_DATE);
        END LOOP;
        CLOSE cur_FIRST;
    END;

并检查结果:

SELECT * FROM TABLEB;

【讨论】:

  • 非常感谢您的回答。我对 %rowtype 有点困惑。抱歉,请您详细解释一下您想通过 %rowtype 实现什么。非常感谢!
  • 查看这个有用的链接:Oracle docs... ...
【解决方案2】:

您的光标解决方案有点令人困惑,我可以看到您可能正在尝试做什么,但这只是不必要的。您不需要使用显式游标并逐行获取它们,insert 语句可以使用select 子句。

您的问题通常通过分析函数来解决,这样您就可以为每个不同的客户对所有行进行排名。顺便说一句,我不知道为什么你会有一个名为TRX_TIMETRX_DATE 的列,在Oracle 中你有一个日期数据类型,它同时存储日期和时间组件。如果我们假设trx_date 是一个日期并且已经填充了时间信息:

insert into tableb (cus_code, trx_no, trx_date, cus_name)
select cus_code, trx_no, trx_date, cus_name
from (
 select cus_code, trx_no, trx_date, cus_name, row_number() over (partition by cus_code order by trx_date) rn
 from   tablea a
)
where rn = 1

请注意,我如何也在插入语句中明确列出我的列,​​而不依赖于表中列的顺序(或者在我不知道的情况下没有添加其他列)。

【讨论】:

  • 感谢 Andrew 提供有关 rownumber() 的信息。我以前从未听说过。至于日期和时间,实际上,我正在考虑在 oracle 中创建一个字符串存储而不是日期,所以我有了它们。非常感谢您的解决方案!
猜你喜欢
  • 2021-06-10
  • 2020-11-08
  • 1970-01-01
  • 2020-10-25
  • 1970-01-01
  • 1970-01-01
  • 2011-02-14
  • 2010-09-25
  • 2019-07-12
相关资源
最近更新 更多