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总结了两个相反的货币对的主要内容,如果未能解决你的问题,请参考以下文章

能避开很多坑的mysql面试题,你知道吗?

数字电路中的竞争冒险以及解决

在机器学习中,怎么对超参数Hyper parameter优化?我总结了以下常见的方法

Mysql学习总结(19)——Mysql无法创建外键的原因

对软件工程这门课程的回顾分析总结

第三周总结Access