在 REdhsift 中编码逻辑时出现“SQL 错误 [XX000]:错误:数字列 2 精度和比例无法合并”

问题描述 投票:0回答:1

这样的代码给我一个错误:“SQL错误[XX000]:错误:数字列2精度和比例无法合并”

WITH RECURSIVE build (PERIOD_START_DATE,PEQ,PREV_PEQ,repeated_patient, cur_rn, max_rn) as (
select 
PERIOD_START_DATE,round(PEQ,1), round(cast(PREV_PEQ as float),1), round(cast(repeated_patient as float),1), cur_rn, max_rn from (       
select 
            PERIOD_START_DATE,
            PEQ,
            cast(PREV_PEQ as float),
            cast(repeated_patient as float),
            ROW_NUMBER() OVER (ORDER BY period_start_date) AS rn
            , 2::int as cur_rn
            , count(1) over() as max_rn

from (select 
            PERIOD_START_DATE,
            round(1.0*SU_VALUE /6, 1)  PEQ,
            LAG(ROUND(1.0*SU_VALUE/6,1 ),1) OVER ( ORDER BY PERIOD_START_DATE ) PREV_PEQ, 
            cast(0 as float) as repeated_patient
      FROM testoss 
     ) where PEQ != PREV_PEQ  ) where rn=1
union all  
select  
            b.PERIOD_START_DATE,
            round(b.PEQ, 1),
            round(b.PREV_PEQ, 1),
 round(cast(case 
    when b.PREV_PEQ - nvl(t.repeated_patient,0) > b.PEQ then b.PEQ
    else b.PREV_PEQ - nvl(t.repeated_patient,0) 
  end as float), 1) as repeated_patient,
   b.cur_rn + 1 AS cur_rn,
   b.max_rn
  from build b join 
  (SELECT period_start_date, PEQ, PREV_PEQ, repeated_patient, lag(period_start_date) over(order by period_start_date) prev_period, 
      ROW_NUMBER() OVER (ORDER BY period_start_date) AS rn from (SELECT 
            PERIOD_START_DATE,
            round(1.0*SU_VALUE /6, 1)  PEQ,
            LAG(ROUND(1.0*SU_VALUE/6,1 ),1) OVER (ORDER BY PERIOD_START_DATE ) PREV_PEQ, 
            cast(0 as float) as repeated_patient
      FROM testoss 
     )) t ON t.prev_period = b.period_start_date
   WHERE t.rn = b.cur_rn AND b.cur_rn <= b.max_rn) 
   select   
            PERIOD_START_DATE,
            PEQ,
            PREV_PEQ,
            repeated_patient
            from build;

给定周期日期 (PERIOD_START_DATE) 和标准单位值 (SU_VALUE),我需要编写以下要求:

• 剂量:在治疗的第1、2、13和14个月服用6片。第三年和第四年没有用药。

• 特定月份内服用该药物的患者总数的计算方法是将该月销售的标准单位 (SU) 除以每月剂量(视为 6 片 (SU))

• 当月新服药患者数按当月上述人数减去重复服药人数计算。一个月的重复患者相当于上个月的新患者。 ○ 我们假设新患者服用第二剂的依从性为 100%,因此计入接下来的 12 个月(下一步)

• 最终患者总数等于最近 12 个月的新患者数量,即当月(计算 TPE)和前 11 个月的新患者数量。

• 总患者等于份额的计算方法是将“使用上述方法计算的总患者等于”除以“所有 MS 产品的总患者等于之和”

这些应该是结果:

enter image description here

以上单元格中的要求和公式都在这里 ->

https://docs.google.com/spreadsheets/d/1xvItLMT8-BcoVjNR-NDIYUTlmTuebP-crD7foSFAwOM/edit?gid=1133570729#gid=1133570729

这是测试数据:

  CREATE TABLE TESTOSS
   (    PERIOD_START_DATE, date, 
    SU integer
   );
Insert into TESTOSS (PERIOD_START_DATE,SU_VALUE) values (to_date('01-SEP-17','DD-MON-RR'),69);
Insert into TESTOSS (PERIOD_START_DATE,SU_VALUE) values (to_date('01-OCT-17','DD-MON-RR'),263);
Insert into TESTOSS (PERIOD_START_DATE,SU_VALUE) values (to_date('01-NOV-17','DD-MON-RR'),684);
Insert into TESTOSS (PERIOD_START_DATE,SU_VALUE) values (to_date('01-DEC-17','DD-MON-RR'),938);
Insert into TESTOSS (PERIOD_START_DATE,SU_VALUE) values (to_date('01-JAN-18','DD-MON-RR'),1352);
Insert into TESTOSS (PERIOD_START_DATE,SU_VALUE) values (to_date('01-FEB-18','DD-MON-RR'),1174);
Insert into TESTOSS (PERIOD_START_DATE,SU_VALUE) values (to_date('01-MAR-18','DD-MON-RR'),1123);
Insert into TESTOSS (PERIOD_START_DATE,SU_VALUE) values (to_date('01-APR-18','DD-MON-RR'),1649);
Insert into TESTOSS (PERIOD_START_DATE,SU_VALUE) values (to_date('01-MAY-18','DD-MON-RR'),1402);
Insert into TESTOSS (PERIOD_START_DATE,SU_VALUE) values (to_date('01-JUN-18','DD-MON-RR'),1548);
Insert into TESTOSS (PERIOD_START_DATE,SU_VALUE) values (to_date('01-JUL-18','DD-MON-RR'),1448);

有人可以帮我解决吗?

对于 Oracle,使用 MODEL 子句解决了这个问题 将Excel公式翻译成SQL查询

WITH METRICS AS
( 
  SELECT 
         PERIOD_START_DATE,
         PEQ,
         PREV_PEQ,
         REPEATED_PATIENT,
         (PEQ - REPEATED_PATIENT) NEW_PATIENT
  FROM
  (  SELECT PERIOD_START_DATE,
            SU_VALUE /6  PEQ,
            LAG (ROUND( SU_VALUE /6),1,0) OVER ( ORDER BY PERIOD_START_DATE ) REV_PEQ,
            0 AS REPEATED_PATIENT
      FROM TESTOSS
      ORDER BY  PERIOD_START_DATE     
   )
   MODEL
      DIMENSION BY (ROW_NUMBER() OVER (ORDER BY PERIOD_START_DATE) RN)
      MEASURES (PRODUCT, PERIOD_START_DATE, PEQ, PREV_PEQ, REPEATED_PATIENT)

   RULES (
          REPEATED_PATIENT [ANY] =
          ( 
               CASE 
                    WHEN PREV_PEQ[CV(RN)]-NVL(REPEATED_PATIENT[CV(RN)-1],0) > PEQ[CV(RN)] THEN PEQ[CV(RN)] 
                    ELSE PREV_PEQ[CV(RN)]-NVL(REPEATED_PATIENT[CV(RN)-1],0) 
                END
            )
        )
)
SELECT 
        PERIOD_START_DATE,
        NEW_PATIENT,
        SUM(NEW_PATIENT) OVER(ORDER BY PERIOD_START_DATE RANGE BETWEEN INTERVAL '11' MONTH PRECEDING AND CURRENT ROW
        ) AS FINAL_PEQ
    FROM METRICS
    ORDER BY PERIOD_START_DATE

但是Redhsift中没有MODEL子句。

用 Redhsift 翻译了类似的案例 将 Excel 公式转换为 Redshift SQL 查询

sql excel amazon-redshift recursive-query analytical
1个回答
0
投票

您收到的错误是由于对不同类型的值进行 UNIONing 造成的。 “1.0*su_value /6”是不受控制范围的 NUMERIC 类型。 你需要照顾好你的类型。我认为当你在其他地方投射到此时你想要浮动。 这运行:

WITH recursive build (period_start_date,peq,prev_peq,repeated_patient, cur_rn, max_rn) AS
(
   SELECT period_start_date,
     round(peq,1),
     round(cast(prev_peq AS FLOAT),1),
     round(cast(repeated_patient AS FLOAT),1),
     cur_rn,
     max_rn
   FROM  (
        SELECT  period_start_date,
           peq,
           cast(prev_peq AS FLOAT),
           cast(repeated_patient AS FLOAT),
           row_number() over (ORDER BY period_start_date) AS rn ,
           2::INT              AS cur_rn ,
           count(1) over()           AS max_rn
        FROM  (
              SELECT  period_start_date,
                 round(1.0*su_value /6, 1)::float                peq,
                 lag(round(1.0*su_value/6,1 ),1) over ( ORDER BY period_start_date )::float  prev_peq,
                 cast(0 AS FLOAT)                  AS repeated_patient
              FROM  testoss 
            )
        WHERE  peq != prev_peq 
      )
   WHERE rn=1
   UNION ALL
   SELECT b.period_start_date,
     round(b.peq, 1),
     round(b.prev_peq, 1),
     round(cast(
     CASE
        WHEN b.prev_peq - nvl(t.repeated_patient,0) > b.peq THEN b.peq
        ELSE b.prev_peq - nvl(t.repeated_patient,0)
     END AS FLOAT), 1) AS repeated_patient,
     b.cur_rn + 1  AS cur_rn,
     b.max_rn
   FROM  build b
   join
     (
        SELECT  period_start_date,
           peq,
           prev_peq,
           repeated_patient,
           lag(period_start_date) over(ORDER BY period_start_date)  prev_period,
           row_number() over (ORDER BY period_start_date)    AS rn
        FROM  (
              SELECT  period_start_date,
                 round(1.0*su_value /6, 1)::float                peq,
                 lag(round(1.0*su_value/6,1 ),1) over (ORDER BY period_start_date )::float  prev_peq,
                 cast(0 AS FLOAT)                  AS repeated_patient
              FROM  testoss )
      ) t
   ON  t.prev_period = b.period_start_date
   WHERE t.rn = b.cur_rn
   AND  b.cur_rn <= b.max_rn
)
SELECT period_start_date,
   peq,
   prev_peq,
   repeated_patient
FROM  build;

此外,请在发布之前运行您的测试用例。 你有语法错误。

© www.soinside.com 2019 - 2024. All rights reserved.