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

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

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

我也可以为每个转换成美元的状态提供正确的总数(参见query 的下半部分,它产生一行

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

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

要创建示例db :(在此下面的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
)`
mysql variables subquery union-all
1个回答
0
投票

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

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

在以前的查询的某些列中gobbledygook的原因是尝试将数字和格式化(文本)数据联合在同一列中。删除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 |

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

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