【问题标题】:Execute query by looping through values within a subquery通过遍历子查询中的值来执行查询
【发布时间】:2021-09-12 23:24:29
【问题描述】:

我不知道我想要实现的目标是否可行,因此我正在与这里的专家联系以提供一些指导。

我创建了一个跨多个 Oracle DB 运行多个查询的 excel 宏。我遇到的一个问题是,其中一个查询在执行期间只能在 where 子句中使用单个值,因为我只需要检索第一行数据(其中 rownum=1),并且可以有数百个这样的唯一值。

我能够执行此操作的唯一方法是在 excel 中创建一系列值,打开数据库连接,执行查询,将结果写回电子表格,关闭连接,然后移动到下一个值在范围内,对范围内的每个值重复此操作。这已被证明是非常低效的,因此我正在寻找一种方法来直接在数据库中循环遍历这些值。

整个查询超过 650 行,但我提供了一个 sn-p 以帮助明确我想要实现的目标。 “START”是子查询的开头,它提取我需要循环的唯一值(GS_GRP_SEQ),“END”是子查询的结尾。

非常感谢您在这方面的帮助!

    SELECT * FROM 
    (SELECT TRIM(CS.CS_NBR) AS CS_Num, TRIM(CS.CS_NAM) AS CName, 
    TO_CHAR(to_date(CS.CS_EFF_DAT,'yyyymmdd'),'mm/dd/yyyy') AS C_Eff_Dte,
    CASE CS.UR_ID
    WHEN 'ABC' THEN 'JOHNNY PARKER'
    WHEN '999' THEN 'UNDEFINED'
    END AS UR_Name,
    G.GS_GRP_SEQ as GR_Num, 
    Case G.GS_STAT
    WHEN '0' THEN 'READY'
    END AS GR_Stat,
    CASE G.GS_FUN_ARR
    WHEN '1' THEN 'INCREASED'
    WHEN '9' THEN 'DECREASED'
    END AS Type_Desc,
    R.RT_TOT_RATE AS RATE_TOT,
    TO_CHAR(to_date(R.RT_TOT_RATE_EFF_DT,'yyyymmdd'),'mm/dd/yyyy') as RT_Eff_Dte, 
    R.RT_TOT_1 as Rate_Type_1, R.RT_AMT_1 as Rate_Amount_1, 
    R.RT_TOT_2 as Rate_Type_2, R.RT_AMT_2 as Rate_Amount_2
    FROM MNDB.CASE CS 
    inner join MNDB.CADR CA on CA.CS_ROOT_KEY = CS.CS_NBR
    inner join MNDB.GRPR G on CS.CS_NBR = G.GS_CS_NBR
    inner join MNDB.GCNT GC on GC.GS_GRP_SEQ = G.GS_GRP_SEQ
    inner join MNDB.TOTR R on R.ACCESS_LEVEL = GC.GS_GRP_SEQ
    INNER JOIN MNDB.PROD P ON TRIM(P.PROD_GRP) = TRIM(G.GS_PROD_CD) 
    LEFT JOIN MNDB.GNAT NAT ON G.GS_GRP_SEQ = NAT.GS_GRP_SEQ
    WHERE CS.CS_NBR = ('123456') 
    AND G.GS_GRP_SEQ IN 
--START--    
   (SELECT DISTINCT GS_GRP_SEQ FROM MNDP.GRPR where CS.CS_NBR = ('123456') and GS_STAT_CD in ('0','2','6') 
--END--
   ORDER BY CA.CS_ADR_PRC_DTE desc, RT_TOT_RATE_EFF_DT desc, RT_TOT_RATE_TERM_DT ASC ) where rownum=1

【问题讨论】:

  • 将电子表格中的所有 IN 子句值写入临时表,然后将其包含在查询中
  • 我不相信该解决方案可以在这里工作,因为我无法使用 IN,因为我需要为给定的 GS_GRP_SEQ 值提取第一行数据(其中 rownum=1)。
  • 所以只需在 ORDER BY 中包含 GS_GRP_SEQ
  • @Brian 试试这个作为测试:select * from dual fetch first row only; 如果运行没有错误,那么您使用的是 12.1 或更高版本,您可能能够稍微简化 fetch-the-first-row 逻辑。
  • @KenWhite 我已按照您的指导进行了建议的修改。谢谢

标签: sql vba oracle adodb


【解决方案1】:

在您的内部 SQL 语句中,添加一个新列,如下所示:

row_number () over (
           partition by <list of columns in each group>
           order by <required columns> desc
         ) rn

然后在外层SQL过滤器中:

where rn=1

【讨论】:

  • 太棒了!这做到了。谢谢!!
【解决方案2】:

使用@NickW 提供的解决方案,我可以通过如下修改代码来达到预期的效果:

    SELECT * FROM 
    (SELECT TRIM(CS.CS_NBR) AS CS_Num, TRIM(CS.CS_NAM) AS CName, 
    TO_CHAR(to_date(CS.CS_EFF_DAT,'yyyymmdd'),'mm/dd/yyyy') AS C_Eff_Dte,
    CASE CS.UR_ID
    WHEN 'ABC' THEN 'JOHNNY PARKER'
    WHEN '999' THEN 'UNDEFINED'
    END AS UR_Name,
    G.GS_GRP_SEQ as GR_Num, 
    Case G.GS_STAT
    WHEN '0' THEN 'READY'
    END AS GR_Stat,
    CASE G.GS_FUN_ARR
    WHEN '1' THEN 'INCREASED'
    WHEN '9' THEN 'DECREASED'
    END AS Type_Desc,
    R.RT_TOT_RATE AS RATE_TOT,
    TO_CHAR(to_date(R.RT_TOT_RATE_EFF_DT,'yyyymmdd'),'mm/dd/yyyy') as RT_Eff_Dte, 
    R.RT_TOT_1 as Rate_Type_1, R.RT_AMT_1 as Rate_Amount_1, 
    R.RT_TOT_2 as Rate_Type_2, R.RT_AMT_2 as Rate_Amount_2,
row_number () over (
           PARTITION BY GS_GRP_SEQ
           ORDER BY GS_GRP_SEQ, CA.CS_ADR_PRC_DTE desc, RT_TOT_RATE_EFF_DT desc, RT_TOT_RATE_TERM_DT ASC
         ) rn
    FROM MNDB.CASE CS 
    inner join MNDB.CADR CA on CA.CS_ROOT_KEY = CS.CS_NBR
    inner join MNDB.GRPR G on CS.CS_NBR = G.GS_CS_NBR
    inner join MNDB.GCNT GC on GC.GS_GRP_SEQ = G.GS_GRP_SEQ
    inner join MNDB.TOTR R on R.ACCESS_LEVEL = GC.GS_GRP_SEQ
    INNER JOIN MNDB.PROD P ON TRIM(P.PROD_GRP) = TRIM(G.GS_PROD_CD) 
    LEFT JOIN MNDB.GNAT NAT ON G.GS_GRP_SEQ = NAT.GS_GRP_SEQ
    WHERE CS.CS_NBR = ('123456') 
    AND G.GS_GRP_SEQ IN    
   (SELECT DISTINCT GS_GRP_SEQ FROM MNDP.GRPR where CS.CS_NBR = ('123456') and GS_STAT_CD in ('0','2','6') 
   ORDER BY GS_GRP_SEQ 
) where rn=1

【讨论】:

    猜你喜欢
    • 2012-03-05
    • 1970-01-01
    • 1970-01-01
    • 2015-07-12
    • 1970-01-01
    • 1970-01-01
    • 2018-11-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多