使用带有子查询和变量的 UNION ALL 的 MySQL 错误

标签 mysql variables subquery union-all

我有一个表 currency_lkp 和一个表 associate_data associate_data 有这些列 - currency, invoice_total 和 status (Unpaid or Paid or WaitingI) 我可以成功地将表与此查询的上半部分 (see MySQL fiddle) 链接起来,并提供每种货币的总计。

我还可以为转换为美元的每个状态提供正确的总计(请参阅 query 的下半部分,它生成一行

当我在两半之间使用 UNION ALL 时,它会在中间三列中产生一个非常奇怪的结果,但在第 4 列和该列的最后一行产生正确的结果。

我认为查询没问题,但如果可以在子查询中使用变量可能会更简洁。任何关于出了什么问题或如何提高优雅的想法将不胜感激 - 谢谢

要创建示例数据库:(MySQL 查询在此下方)

    CREATE TABLE IF NOT EXISTS `currency_lkp` (
  `currency_id` int(11) NOT NULL AUTO_INCREMENT,
  `currency` varchar(10) NOT NULL,
  `currency_label` varchar(100) NOT NULL,
  `currency_description` varchar(100) NOT NULL,
  `exchange_rate_USD` float NOT NULL,
  PRIMARY KEY (`currency_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=6 ;

INSERT INTO `currency_lkp` (`currency_id`, `currency`, 
`currency_label`, `currency_description`, `exchange_rate_USD`)
VALUES
(1, 'GBP', '£', 'Great British Pound (Sterling)', 0.75),
(2, 'Euro', '€', 'Euro currency for the Euro Zone', 0.85),
(3, 'USD', '$', 'United States Dollars', 1),
(4, 'CLP', '$', 'Chilean Pesos', 639.85),
(5, 'INR', '&#8377', 'Indian Rupees', 64.8);

CREATE TABLE IF NOT EXISTS `associate_data` (`associate_data_id`
int(11) NOT NULL AUTO_INCREMENT,
`currency` varchar(10) NOT NULL, 
`status` varchar(20) NOT NULL, 
`invoice_total` float,
 PRIMARY KEY (`associate_data_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=6 ;

INSERT INTO `associate_data` (`associate_data_id`, `currency`, 
`status`, `invoice_total`)
 VALUES
(1, 'GBP', 'Paid', 200),
(2, 'GBP', 'Unpaid', 300),
(3, 'Euro', 'Paid', 1000),
(4, 'Euro', 'Unpaid', 2000),
(5, 'USD', 'Paid', 1200),
(6, 'USD', 'Unpaid', 1400),
(7, 'GBP', 'WaitingInvoice', 400),
(8, 'Euro', 'WaitingInvoice', 1300),
(9, 'USD', 'WaitingInvoice', 2300),
(10, 'CLP', 'Paid', 100200),
(11, 'CLP', 'Unpaid', 110400),
(12, 'CLP', 'WaitingInvoice', 11200);

MySQL Query in full:
`
(
SELECT cl.currency,
(SELECT SUM(invoice_total) FROM associate_data ad2
WHERE ad2.currency = cl.currency  AND ad2.status = 'Paid') AS Paid,
(SELECT SUM(invoice_total) FROM associate_data ad3
WHERE ad3.currency = cl.currency  AND ad3.status = 'Unpaid') AS Unpaid,
(SELECT SUM(invoice_total) FROM associate_data ad4
WHERE ad4.currency = cl.currency  AND ad4.status = 'WaitingInvoice') AS WaitingInvoice,
(SELECT IFNULL(Unpaid,0) + IFNULL(WaitingInvoice, 0)) AS TotalToPay
FROM currency_lkp cl
)

UNION ALL

(
SELECT 'Total in USD',

FORMAT(
SUM(IFNULL(
(SELECT SUM(invoice_total) FROM associate_data ad5
WHERE ad5.currency = clu.currency AND (ad5.status = 'Paid'))
,0.1)/clu.exchange_rate_USD)
,0) AS TotalUSDPaid,

FORMAT(
SUM(IFNULL(
(SELECT SUM(invoice_total) FROM associate_data ad6
WHERE ad6.currency = clu.currency AND (ad6.status = 'Unpaid'))
,0.1)/clu.exchange_rate_USD)
,0) AS TotalUSDUnpaid,

FORMAT(
SUM(IFNULL(
(SELECT SUM(invoice_total) FROM associate_data ad6
WHERE ad6.currency = clu.currency AND (ad6.status = 'WaitingInvoice'))
,0.1)/clu.exchange_rate_USD)
,0) AS TotalUSDWaitingInvoice,

FORMAT(
SUM(IFNULL(
(SELECT SUM(invoice_total) FROM associate_data ad6
WHERE ad6.currency = clu.currency AND (ad6.status = 'WaitingInvoice' OR ad6.status = 'Unpaid'))
,0.1)/clu.exchange_rate_USD)
,0) AS TotalUSDToPay
FROM currency_lkp clu
)`

最佳答案

您可以通过使用“条件聚合”(聚合函数内的 case 表达式)来从根本上简化您的查询(并提高效率),如下所示:

select
      cu.currency
    , sum(case when ad.status = 'Paid' then invoice_total end) as Paid
    , sum(case when ad.status = 'Unpaid' then invoice_total end) as Unpaid
    , sum(case when ad.status = 'WaitingInvoice' then invoice_total end) as WaitingInvoice_USD
    , FORMAT(sum(case when ad.status = 'Paid' then invoice_total/cu.exchange_rate_USD end),0) as Paid_USD
    , FORMAT(sum(case when ad.status = 'Unpaid' then invoice_total/cu.exchange_rate_USD end),0) as Unpaid_USD
    , FORMAT(sum(case when ad.status = 'WaitingInvoice' then invoice_total/cu.exchange_rate_USD end),0) as WaitingInvoice_USD  
FROM associate_data ad
inner join currency_lkp cu ON ad.currency = cu.currency
group by
      cu.currency
union all
select
      'Total'
    , sum(case when ad.status = 'Paid' then invoice_total end) as Paid
    , sum(case when ad.status = 'Unpaid' then invoice_total end) as Unpaid
    , sum(case when ad.status = 'WaitingInvoice' then invoice_total end) as WaitingInvoice_USD
    , FORMAT(sum(case when ad.status = 'Paid' then invoice_total/cu.exchange_rate_USD end),0) as Paid_USD
    , FORMAT(sum(case when ad.status = 'Unpaid' then invoice_total/cu.exchange_rate_USD end),0) as Unpaid_USD
    , FORMAT(sum(case when ad.status = 'WaitingInvoice' then invoice_total/cu.exchange_rate_USD end),0) as WaitingInvoice_USD  
FROM associate_data ad
inner join currency_lkp cu ON ad.currency = cu.currency
;

该查询产生以下结果:

| currency |   Paid | Unpaid | WaitingInvoice_USD | Paid_USD | Unpaid_USD | WaitingInvoice_USD |
|----------|--------|--------|--------------------|----------|------------|--------------------|
|      CLP | 100200 | 110400 |              11200 |      157 |        173 |                 18 |
|     Euro |   1000 |   2000 |               1300 |    1,176 |      2,353 |              1,529 |
|      GBP |    200 |    300 |                400 |      267 |        400 |                533 |
|      USD |   1200 |   1400 |               2300 |    1,200 |      1,400 |              2,300 |
|    Total | 102600 | 114100 |              15200 |    2,800 |      4,325 |              4,380 |

查看此演示:http://sqlfiddle.com/#!9/b4b5bb/36

您之前查询的某些列中出现乱码的原因是试图合并同一列中的数字和格式化(文本)数据。删除 format( ,0)

参见:http://sqlfiddle.com/#!9/b4b5bb/37

(
SELECT cl.currency,
(SELECT SUM(invoice_total) FROM associate_data ad2
WHERE ad2.currency = cl.currency  AND ad2.status = 'Paid') AS Paid,
(SELECT SUM(invoice_total) FROM associate_data ad3
WHERE ad3.currency = cl.currency  AND ad3.status = 'Unpaid') AS Unpaid,
(SELECT SUM(invoice_total) FROM associate_data ad4
WHERE ad4.currency = cl.currency  AND ad4.status = 'WaitingInvoice') AS WaitingInvoice,
(SELECT IFNULL(Unpaid,0) + IFNULL(WaitingInvoice, 0)) AS TotalToPay
FROM currency_lkp cl
)
UNION ALL
(
SELECT 'Total in USD',


SUM(IFNULL(
(
  SELECT SUM(invoice_total) FROM associate_data ad5
WHERE ad5.currency = clu.currency AND (ad5.status = 'Paid')
),0.1)/clu.exchange_rate_USD) 
  AS TotalUSDPaid,


SUM(IFNULL(
(SELECT SUM(invoice_total) FROM associate_data ad6
WHERE ad6.currency = clu.currency AND (ad6.status = 'Unpaid'))
,0.1)/clu.exchange_rate_USD)
 AS TotalUSDUnpaid,


SUM(IFNULL(
(SELECT SUM(invoice_total) FROM associate_data ad6
WHERE ad6.currency = clu.currency AND (ad6.status = 'WaitingInvoice'))
,0.1)/clu.exchange_rate_USD)
 AS TotalUSDWaitingInvoice,


SUM(IFNULL(
(SELECT SUM(invoice_total) FROM associate_data ad6
WHERE ad6.currency = clu.currency AND (ad6.status = 'WaitingInvoice' OR ad6.status = 'Unpaid'))
,0.1)/clu.exchange_rate_USD)
 AS TotalUSDToPay
FROM currency_lkp clu
)

查询的结果是:

|     currency |               Paid |           Unpaid |    WaitingInvoice |        TotalToPay |
|--------------|--------------------|------------------|-------------------|-------------------|
|          GBP |                200 |              300 |               400 |               700 |
|         Euro |               1000 |             2000 |              1300 |              3300 |
|          USD |               1200 |             1400 |              2300 |              3700 |
|          CLP |             100200 |           110400 |             11200 |            121600 |
|          INR |             (null) |           (null) |            (null) |                 0 |
| Total in USD | 2799.7379740260294 | 4325.48309943104 | 4380.250701542091 | 8705.732257763328 |

注意:我没有尝试更正任何查询算法,但显然其中一个是错误的

关于使用带有子查询和变量的 UNION ALL 的 MySQL 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47856260/

相关文章:

sql - 别名在子查询中传递错误数据

mysql - 子查询(以及带有连接的查询)不使用 MySQL 索引 (MyISAM)

Mysql更新失败,有子查询

Javascript:从字符串初始化变量?

variables - 在Lua中不等于或等于

c# - 对已分配的字符串使用未分配的局部变量错误

带有字段名称的 MySql AF​​TER UPDATE 触发器

php - 如何获取具有相同条件的表格2的值

php - 优先在 php 中打印数组值

mysql - 如何将查询结果限制为精确的组匹配