MySQL总结了两个相反的货币对
Posted
技术标签:
【中文标题】MySQL总结了两个相反的货币对【英文标题】:MySQL sum up two opposite currency pairs 【发布时间】:2015-04-23 17:36:23 【问题描述】:我在表格中有以下买卖货币对及其值,我试图编写一个小的选择语句来获取每对的总数,但是当货币对有相反时,它们可以相互扣除,因为例如,卖出任何欧元是没有意义的,因为它可以用来抵消一些买入的欧元。所以两条线 GBP/EUR, EUR/GBP 会变成: 请注意,这些货币对可能不仅匹配 EUR/GBP,因此不能硬编码
EUR 852.07 GBP -636.1
(也许专注于减少购买量是要走的路?)
我很想给你举个例子,但我完全被困住了!任何想法都非常感谢。
Buy Sell
ccy amt ccy amt
EUR, 1409.7600, AUD, -1965.4900
GBP, 2801.8500, AUD, -5446.5100
EUR, 1116.2800, CAD, -1472.1500
EUR, 4862.2000, CHF, -5013.9000
GBP, 3937.6700, CHF, -5661.5700
EUR, 2066.8900, DKK, -15505.0000
GBP, 1688.7200, DKK, -17640.6400
**
GBP, 1986.4400, EUR, -2778.7500
EUR, 3630.8200, GBP, -2622.5400
**
EUR, 358.4100, NOK, -3046.6600
GBP, 2865.9800, NOK, -33965.5900
EUR, 1574.9800, SEK, -14746.0600
GBP, 1511.3100, SEK, -19727.5900
EUR, 724.3600, USD, -777.8900
GBP, 34.7400, USD, -52.0200
ccy = currency char(3)
amt = amount decimal
那么最终的结果应该是这样的。
Buy Sell
ccy amt ccy amt
EUR, 1409.7600, AUD, -1965.4900
GBP, 2801.8500, AUD, -5446.5100
EUR, 1116.2800, CAD, -1472.1500
EUR, 4862.2000, CHF, -5013.9000
GBP, 3937.6700, CHF, -5661.5700
EUR, 2066.8900, DKK, -15505.0000
GBP, 1688.7200, DKK, -17640.6400
**
EUR, 852.07 GBP, -636.1
**
EUR, 358.4100, NOK, -3046.6600
GBP, 2865.9800, NOK, -33965.5900
EUR, 1574.9800, SEK, -14746.0600
GBP, 1511.3100, SEK, -19727.5900
EUR, 724.3600, USD, -777.8900
GBP, 34.7400, USD, -52.0200
【问题讨论】:
而该表的架构将是...... ??? 对不起,我认为这很明显;添加了一个快速架构 其实这些是数据类型,方案(见我的回答)将包括表名、列名、列类型等。 你有货币表吗?每种货币都有 id 吗? 我会这样做,但是这会带来什么好处,因为货币与 id 一样独特 【参考方案1】:我不得不稍微更改您的列名以反映同一记录中有多个 ccy 和 amt 的事实。
SELECT
a.buy_ccy,
SUM(a.buy_amt) + COALESCE(SUM(b.sell_amt),0) as buy_amt,
a.sell_ccy,
SUM(a.sell_amt) + COALESCE(SUM(b.buy_amt),0) as sell_amt
FROM
transactions as a
LEFT OUTER JOIN transactions as b ON (a.buy_ccy = b.sell_ccy AND a.sell_ccy = b.buy_ccy)
GROUP BY
a.buy_ccy,
b.buy_ccy,
a.sell_ccy,
b.sell_ccy
HAVING buy_amt > 0;
示例: http://sqlfiddle.com/#!9/f2006/3
【讨论】:
这是我一直在尝试的方式。待会儿会试一试。就在我回家的路上。 当我运行这个时,我得到GBP 714.24 EUR -1074.61
查看我提供的链接。您的设置有何不同?【参考方案2】:
试试这个:
SELECT SUM( CASE
WHEN `ccy_buy` = 'EUR' AND `ccy_sell` = 'GBP' THEN `amt_buy`
WHEN `ccy_sell` = 'EUR' AND `ccy_buy` = 'GBP' THEN `amt_sell`
END
) AS `ccy1`,
SUM( CASE
WHEN `ccy_buy` = 'GBP' and `ccy_sell` = 'EUR' THEN `amt_buy`
WHEN `ccy_sell` = 'GBP' and `ccy_buy` = 'EUR' THEN `amt_sell`
END
) AS `ccy2`
FROM `test`
您可能希望将其包装到存储过程中并将两种货币作为参数传递,如下所示:
DELIMITER ;;
CREATE PROCEDURE `sp_compareCurrencyPairs`(IN pCur1 CHAR(3), IN pCur2 CHAR(3))
READS SQL DATA
BEGIN
SELECT SUM( CASE
WHEN `ccy_buy` = pCur1 AND `ccy_sell` = pCur2 THEN `amt_buy`
WHEN `ccy_sell` = pCur1 AND `ccy_buy` = pCur2 THEN `amt_sell`
END
) AS `ccy1`,
SUM( CASE
WHEN `ccy_buy` = pCur2 AND `ccy_sell` = pCur1 THEN `amt_buy`
WHEN `ccy_sell` = pCur2 AND `ccy_buy` = pCur1 THEN `amt_sell`
END
) AS `ccy2`
FROM `test`;
END;;
DELIMITER ;
然后像这样使用它:
CALL `sp_compareCurrencyPairs`('GBP', 'EUR');
【讨论】:
这是一个有趣的想法,我尝试了许多变体,但它从未给出正确的结果。答案实际上必须是动态的(所以不能用 EUR、GBP 硬编码)并且还必须考虑所有其他货币对 所以您需要查询一次返回所有配对结果,还是一次返回一对?用存储过程检查我的编辑。我使用您示例中的数据在本地进行了尝试,它似乎返回了您期望的结果。 一个大镜头会很好,否则我可以把它拉进python并在那里做【参考方案3】:尝试这样的事情并假设您使用的是 php...
$sql = "
select
sum(
case
when buy_currency = '$currency_one' then buy_amount
when sell_currency = '$currency_one' then sell_amount
end
) as first_currency,
sum(
case
when buy_currency = '$currency_twp' then buy_amount
when sell_currency = '$currency_two' then sell_amount
end
) as second_currency
from test";
假设架构像
CREATE TABLE `test` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`buy_currency` VARCHAR(50) NOT NULL DEFAULT '0',
`buy_amount` VARCHAR(50) NOT NULL DEFAULT '0',
`sell_currency` VARCHAR(50) NOT NULL DEFAULT '0',
`sell_amount` VARCHAR(50) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
)
COLLATE='latin1_swedish_ci'
ENGINE=InnoDB
AUTO_INCREMENT=6
;
【讨论】:
这只会给出总和而不是组对。事实上,它给了first_currency 12964.9500, second_currency 12204.1700
好的 - 谢谢你的想法。答案实际上必须是动态的(所以不能用 EUR、GBP 进行硬编码)并且还必须考虑所有其他货币对。【参考方案4】:
http://sqlfiddle.com/#!9/d5198/1
SELECT
IF(buy_ccy>sell_ccy,buy_ccy,sell_ccy) as buy_ccy,
SUM(IF(buy_ccy>sell_ccy,buy_amt,sell_amt)) as buy_amt,
IF(buy_ccy>sell_ccy,sell_ccy,buy_ccy) as sell_ccy,
SUM(IF(buy_ccy>sell_ccy,sell_amt,buy_amt)) as sell_amt
FROM EXCHANGE
GROUP BY IF(buy_ccy>sell_ccy,CONCAT(buy_ccy,sell_ccy),CONCAT(sell_ccy,buy_ccy))
【讨论】:
这确实是一种有趣的方法,但它通常会使买入消极而卖出积极。 否定或肯定,但它必须是所有记录的相同规则。因此,要更改查询,您只需将自己的规则应用于查询。所以如果两个 amt 都是正面的,你可以SUM(IF(buy_ccy>sell_ccy,buy_amt,-sell_amt)) as buy_amt,
以上是关于MySQL总结了两个相反的货币对的主要内容,如果未能解决你的问题,请参考以下文章