【问题标题】:Select query with calculated field that uses subquery with multiple conditions选择带有计算字段的查询,该字段使用具有多个条件的子查询
【发布时间】:2018-07-09 20:01:33
【问题描述】:

三个表:

COST_SAVINGS:COST_SAVINGS_ID、ONE_TIME_CREDIT、CREATION_DATE、INVOICE_ID(FK 到 Invoice 表)

INVOICE: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 子句(尝试匹配货币代码)。我不确定如何解决它。有什么想法吗?

【问题讨论】:

    标签: mysql select subquery calculated-columns


    【解决方案1】:

    尝试将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)
    

    【讨论】:

    • 感谢您的建议。我根据您的建议添加了 LIMIT 1,现在我收到一条错误消息,提示我缺少括号。我正在编写的查询是通过供应商的门户网站进行的,因此错误消息并没有太大帮助。我已经看到它为奇怪的非括号相关问题抛出了几次,所以我不一定相信它。我是否可以考虑另一种方法,而不是使用子查询来计算 SELECT 查询中的字段?再次感谢您!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多