我在SQL查询中做错了什么?

时间:2013-09-20 08:13:09

标签: sql oracle

我是if-then SQL语句的新手。我只知道基础知识(选择,更新,插入连接等),所以如果你能帮我解决这个场景中的语法会很有帮助。

我有一张桌子可以保存客户的活动,假设我是牙医,我存储了一个特定的活动,当我使用我的软件检查客户应该支付的费用时,我使用了这个查询:

SELECT ACTIVITY.ID, 
       ACTIVITY.DATES, 
       ACTIVITY.INSURANCE_ID 
       ACTIVITY.AMOUNT, 
       ACTIVITY.INSURANCE_AMOUNT, 
       ACTIVITY.AMOUNT * ((100 - ACTIVITY.INSURANCE_AMOUNT) / 100) AS AMOUNT_TO_PAY, 
       ACTIVITY.TIME, 
       ACTIVITY.MONEY_RECEIVED,
       ACTIVITY.ROWID
FROM ACTIVITY
LEFT JOIN INSURANCE ON INSURANCE.ID = ACTIVITY.INSURANCE_ID 
WHERE ACTIVITY.ID = :patient_id AND ACTIVITY.MONEY_RECEIVED IS NULL

此查询选择我需要的数据加上客户应支付的金额,计算保险金额的折扣百分比,并返回总金额以支付金额(AMOUNT_TO_PAY)。

这很好用,但问题是,即使保险已过期,也会进行此计算。我想用if-then或ORACLE JDEVELOPER中的任何其他方法创建一个SQL语句,首先检查我的表CUSTOMER_INSURANCE.TO_DATE是否仍处于活动状态;如果是,做计算;如果DATE已过期,请不要包含保险百分比。

这是我正在尝试执行的查询,但我做错了什么:

IF ((SELECT count(*) FROM CUSTOMER_INSURANCE.TO_DATE TO_DATE 
    WHERE TO_DATE >= sysdate AND customer_id = :patient_id) > 0)
SELECT ACTIVITY.ID, 
       ACTIVITY.DATES, 
       ACTIVITY.INSURANCE_ID 
       ACTIVITY.AMOUNT, 
       ACTIVITY.INSURANCE_AMOUNT, 
       ACTIVITY.AMOUNT * ((100 - ACTIVITY.INSURANCE_AMOUNT) / 100) AS AMOUNT_TO_PAY, 
       ACTIVITY.TIME, 
       ACTIVITY.MONEY_RECEIVED,
       ACTIVITY.ROWID
FROM ACTIVITY
LEFT JOIN INSURANCE ON INSURANCE.ID = ACTIVITY.INSURANCE_ID 
WHERE ACTIVITY.ID = :patient_id AND ACTIVITY.MONEY_RECEIVED IS NULL
ELSE IF ((SELECT count(*) FROM CUSTOMER_INSURANCE.TO_DATE TO_DATE 
    WHERE TO_DATE >= sysdate AND customer_id = :patient_id) = 0)
SELECT ACTIVITY.ID, 
       ACTIVITY.DATES, 
       ACTIVITY.INSURANCE_ID 
       ACTIVITY.AMOUNT, 
       ACTIVITY.INSURANCE_AMOUNT, 
       ACTIVITY.AMOUNT AS AMOUNT_TO_PAY, 
       ACTIVITY.TIME, 
       ACTIVITY.MONEY_RECEIVED,
       ACTIVITY.ROWID
FROM ACTIVITY
LEFT JOIN INSURANCE ON INSURANCE.ID = ACTIVITY.INSURANCE_ID 
WHERE ACTIVITY.ID = :patient_id AND ACTIVITY.MONEY_RECEIVED IS NULL

有人可以帮我完成这个查询吗?

4 个答案:

答案 0 :(得分:1)

您可以添加CASE表达式以有条件地返回ACTIVITY.INSURANCE_AMOUNT值:

SELECT ACTIVITY.ID, 
       ACTIVITY.DATES, 
       ACTIVITY.INSURANCE_ID 
       ACTIVITY.AMOUNT, 
       ACTIVITY.INSURANCE_AMOUNT, 
       ACTIVITY.AMOUNT * (1 - CASE
                                WHEN EXISTS (
                                  SELECT *
                                  FROM CUSTOMER_INSURANCE.TO_DATE
                                  WHERE TO_DATE >= sysdate
                                    AND customer_id = :patient_id
                                )
                                THEN ACTIVITY.INSURANCE_AMOUNT
                                ELSE 0
                              END / 100) AS AMOUNT_TO_PAY,
       ACTIVITY.TIME, 
       ACTIVITY.MONEY_RECEIVED,
       ACTIVITY.ROWID

FROM ACTIVITY

LEFT JOIN INSURANCE ON INSURANCE.ID = ACTIVITY.INSURANCE_ID 

WHERE ACTIVITY.ID = :patient_id AND ACTIVITY.MONEY_RECEIVED IS NULL
;

CUSTOMER_INSURANCE.TO_DATE中存在匹配的行时,将返回ACTIVITY.INSURANCE_AMOUNT值以计算剩余金额,否则返回0,因此整个表达式的计算结果为ACTIVITY.AMOUNT

注意:

  1. “支付百分比”计算已从(100 - x) / 100更改为等效(并略短)1 - x/100表单。

  2. (SELECT COUNT(*) FROM ...) > 0谓词已替换为效率更高的EXISTS (SELECT * FROM ...)谓词。

答案 1 :(得分:0)

 IF CUSTOMER_INSURANCE.TO_DATE >= GetDate()  THEN
  ACTIVITY.AMOUNT * ((100 - ACTIVITY.INSURANCE_AMOUNT) / 100);
   ELSE ACTIVITY.AMOUNT;

先前的声明是否有效?请注意,这尚未经过测试。

答案 2 :(得分:0)

如果您使用的是Oracle,那么使用关键字TO_DATE或DATES,TIME作为列别名可能会引发错误是一种不好的做法。此外,您不需要IF ELSE语句,因为这可以在正常的UNION ALL中实现。

SELECT
      ACTIVITY.ID,
      ACTIVITY.DATES,
      ACTIVITY.INSURANCE_ID,
      ACTIVITY.AMOUNT,
      ACTIVITY.INSURANCE_AMOUNT,
      CASE
          WHEN TO_DATE >= SYSDATE
          THEN
              ACTIVITY.AMOUNT
              * ( ( 100
                  - ACTIVITY.INSURANCE_AMOUNT )
                / 100 )
          ELSE
              ACTIVITY.AMOUNT
      END
          AS AMOUNT_TO_PAY,
      ACTIVITY.TIME,
      ACTIVITY.MONEY_RECEIVED,
      ACTIVITY.ROWID
FROM
      CUSTOMER_INSURANCE,
          ACTIVITY
      LEFT JOIN
          INSURANCE
      ON INSURANCE.ID = ACTIVITY.INSURANCE_ID
WHERE
         ACTIVITY.ID = :PATIENT_ID
      AND ACTIVITY.MONEY_RECEIVED IS NULL
      AND CUSTOMER_ID = :PATIENT_ID

答案 3 :(得分:0)

我认为这应该有效。您可以根据您的要求更改CASE。

select  ACTIVITY.ID, 
       ACTIVITY.DATES, 
       ACTIVITY.INSURANCE_ID 
       ACTIVITY.AMOUNT, 
       ACTIVITY.INSURANCE_AMOUNT,
       CASE WHEN  TO_DATE >= sysdate 
                THEN  ACTIVITY.AMOUNT * ((100 - ACTIVITY.INSURANCE_AMOUNT) / 100)
                WHEN TO_DATE < sysdate
                THEN  ACTIVITY.AMOUNT
                END AS AMOUNT_TO_PAY
FROM 
(
SELECT ACTIVITY.ID, 
       ACTIVITY.DATES, 
       ACTIVITY.INSURANCE_ID 
       ACTIVITY.AMOUNT, 
       ACTIVITY.INSURANCE_AMOUNT, 
       ACTIVITY.AMOUNT  
       ACTIVITY.TIME, 
       ACTIVITY.MONEY_RECEIVED,
       ACTIVITY.ROWID
FROM ACTIVITY
LEFT JOIN INSURANCE ON INSURANCE.ID = ACTIVITY.INSURANCE_ID 
WHERE ACTIVITY.ID = :patient_id AND ACTIVITY.MONEY_RECEIVED IS NULL
)
WHERE ACTIVITY.ID = :patient_id;

谢谢, 阿迪亚