选择具有计算字段的查询,该查询使用具有多个条件的子查询

时间:2018-07-09 20:01:34

标签: mysql select subquery calculated-columns

三个表:

COST_SAVINGS:COST_SAVINGS_ID,ONE_TIME_CREDIT,CREATION_DATE,INVOICE_ID(从FK到发票表)

发票:INVOICE_ID,INVOICE_CURRENCY_CODE

EXCHANGE_RATE:CURRENCY_RATE,CURRENCY_DATE

我正在报告“成本节省”(第一张表)。挑战在于,每个成本节省金额都可以使用不同的货币,因此我需要一个字段来显示基于发票表中的货币以及Exchange.Ex_Date和Cost_Savings.Create_Date之间匹配的月/年的转换金额。

我收到一条错误消息,指出:

  

单行子查询返回多行

这是我到目前为止所拥有的:

SELECT 
COST_SAVINGS.COST_SAVINGS_ID, 
COST_SAVINGS.CLAIM_TYPE, 
COST_SAVINGS.COMMENTS, 
COST_SAVINGS.COST_SAVINGS_STATUS, 
COST_SAVINGS.CREATION_DATE, 
COST_SAVINGS.DESCRIPTION,
COST_SAVINGS.ONE_TIME_CREDIT AS CREDIT_IN_NATIVE_CURRENCY,
FINANCE_INVOICE.CURRENCY_CODE,
COST_SAVINGS.ONE_TIME_CREDIT * 
    (SELECT EXCHANGE_RATE.CURRENCY_RATE 
     FROM EXCHANGE_RATE 
     WHERE EXTRACT (MONTH FROM COST_SAVINGS.CREATION_DATE) = EXTRACT (MONTH FROM EXCHANGE_RATE.CURRENCY_DATE)
     AND EXTRACT (YEAR FROM COST_SAVINGS.CREATION_DATE) = EXTRACT (YEAR FROM EXCHANGE_RATE.CURRENCY_DATE)
     AND FINANCE_INVOICE.CURRENCY_CODE = EXCHANGE_RATE.CURRENCY_CODE) AS CREDIT_IN_USD

FROM COST_SAVINGS

LEFT JOIN FINANCE_INVOICE ON COST_SAVINGS.INVOICE_ID = FINANCE_INVOICE.INVOICE_ID

我觉得问题可能出在子查询中的第三个WHERE子句中(试图匹配货币代码)。我不确定如何解决。有什么想法吗?

1 个答案:

答案 0 :(得分:0)

尝试将LIMIT 1放在子查询中:

...RENCY_CODE = EXCHANGE_RATE.CURRENCY_CODE LIMIT 1) AS CREDIT_IN_USD

我相信您的子查询返回多行。当您在SELECT子句中使用子查询代替列名时,这种方法不起作用。

如果您不想使用子查询来代替列名,请尝试这样的操作。您将加入子查询生成的虚拟表。

这是汇率的虚拟表。它使用GROUP BY进行一行(或每个月/年/货币代码中不包含行。如果原始表中的任何月/年/代码中不止一行,则使用AVG()进行平均) 。您也可以使用MAX()MIN()

          SELECT AVG(CURRENCY_RATE) CURRENCY_RATE,
                 CURRENCY_CODE,
                 EXTRACT(MONTH FROM CURRENCY_DATE) MONTH,
                 EXTRACT(YEAR FROM CURRENCY_DATE) YEAR
            FROM EXCHANGE_RATE 
           GROUP BY CURRENCY_CODE, 
                 EXTRACT(MONTH FROM CURRENCY_DATE),
                 EXTRACT(YEAR FROM CURRENCY_DATE)

尝试一下,并说服自己。

然后将其构建到您的整体查询中。

SELECT 
      COST_SAVINGS.COST_SAVINGS_ID, 
      COST_SAVINGS.whatever,   ...   
      FINANCE_INVOICE.CURRENCY_CODE,
      (COST_SAVINGS.ONE_TIME_CREDIT * RATE.CURRENCY_RATE) AS CREDIT_IN_USD
FROM COST_SAVINGS
LEFT JOIN FINANCE_INVOICE ON COST_SAVINGS.INVOICE_ID = FINANCE_INVOICE.INVOICE_ID
LEFT JOIN (SELECT AVG(CURRENCY_RATE) CURRENCY_RATE,
                 CURRENCY_CODE,
                 EXTRACT(MONTH FROM CURRENCY_DATE) MONTH,
                 EXTRACT(YEAR FROM CURRENCY_DATE) YEAR
            FROM EXCHANGE_RATE 
           GROUP BY CURRENCY_CODE, 
                 EXTRACT(MONTH FROM CURRENCY_DATE),
                 EXTRACT(YEAR FROM CURRENCY_DATE)
    ) RATE ON RATE.CURRENCY_CODE = FINANCE_INVOICE.CURRENCY_CODE
          AND RATE.YEAR  = EXTRACT(YEAR  FROM COST_SAVINGS.CREATION_DATE)
          AND RATE.MONTH = EXTRACT(MONTH FROM COST_SAVINGS.CREATION_DATE)