如何使用IF条件对LEFT JOIN进行单个查询?

时间:2018-06-08 15:54:11

标签: php mysql

我有这个名为profit_loss的表:

+--------------------+------------+----------+-------------+------------------+
| timestamp          | fee        | fee_unit | profit_loss | profit_loss_unit |
+--------------------+------------+----------+-------------+------------------+
| lm83-1526098952020 | 0.00750007 | BNB      |  0.09672160 | USDT             |
| lm83-1526098952020 | 0.00750007 | BNB      |  0.00000000 | BNB              |
| lm83-1526098952020 | 0.00750007 | BNB      |  0.00000050 | BTC              |
+--------------------+------------+----------+-------------+------------------+

并且还有这个,名为trading_price

+--------------------+-----------+---------------+---------------+
| timestamp          | pair_name | bid_price     | ask_price     |
+--------------------+-----------+---------------+---------------+
| lm83-1526098952020 | NEOUSDT   |   63.14000000 |   63.20000000 |
| lm83-1526098952020 | NEOBTC    |    0.00749700 |    0.00749900 |
| lm83-1526098952020 | NEOETH    |    0.09287900 |    0.09319500 |
| lm83-1526098952020 | NEOBNB    |    4.95100000 |    4.96700000 |
| lm83-1526098952020 | BNBUSDT   |   12.73850000 |   12.74580000 |
| lm83-1526098952020 | BNBBTC    |    0.00151130 |    0.00151190 |
| lm83-1526098952020 | BNBETH    |    0.01873500 |    0.01876000 |
| lm83-1526098952020 | LTCBNB    |   10.73000000 |   10.77000000 |
| lm83-1526098952020 | BCCBNB    |  107.73000000 |  108.37000000 |
| lm83-1526098952020 | LTCUSDT   |  136.80000000 |  137.14000000 |
| lm83-1526098952020 | LTCBTC    |    0.01625800 |    0.01627000 |
| lm83-1526098952020 | LTCETH    |    0.20172000 |    0.01627000 |
| lm83-1526098952020 | BCCUSDT   | 1372.01000000 | 1374.11000000 |
| lm83-1526098952020 | BCCBTC    |    0.16314900 |    0.16315100 |
| lm83-1526098952020 | BCCETH    |    2.02004000 |    2.02785000 |
| lm83-1526098952020 | BTCUSDT   | 8412.13000000 | 8412.14000000 |
| lm83-1526098952020 | ETHUSDT   |  677.88000000 |  678.55000000 |
| lm83-1526098952020 | ETHBTC    |    0.08055000 |    0.08060500 |
+--------------------+-----------+---------------+---------------+

如何LEFT JOIN这些表,以便结果如下?

+--------------------+------------+----------+-------------+------------------+-----------+---------------+---------------+
| timestamp          | fee        | fee_unit | profit_loss | profit_loss_unit | pair_name | bid_price     | ask_price     |
+--------------------+------------+----------+-------------+------------------+-----------+---------------+---------------+
| lm83-1526098952020 | 0.00750007 | BNB      |  0.09672160 | USDT             | BNBUSDT   |   12.73850000 |   12.74580000 |
| lm83-1526098952020 | 0.00750007 | BNB      |  0.00000000 | BNB              | BNBBNB    |    1          |    1          |
| lm83-1526098952020 | 0.00750007 | BNB      |  0.00000050 | BTC              | BNBBTC    |    0.00151130 |    0.00151190 |
+--------------------+------------+----------+-------------+------------------+-----------+---------------+---------------+

请注意,基于trading_price.pair_nameprofit_loss.fee_unit合并,我只需要profit_loss.profit_loss_unit

但如果条件如下:

profit_loss.fee_unitprofit_loss.profit_loss_unit

组合不存在,然后尝试相反的方式:

profit_loss.profit_loss_unitprofit_loss.fee_unit

如何对LEFT JOIN IF这样的条件进行单一查询?

1 个答案:

答案 0 :(得分:1)

我们可以使用两个左连接操作,尝试获取两个匹配的行,然后使用SELECT列表中的表达式来测试是否找到了匹配的行。

SELECT p.timestamp
     , ...

     , CASE WHEN t.timestamp IS NOT NULL
        THEN t.pairname
        ELSE r.pairname
       END AS pairname

     , CASE WHEN t.timestamp IS NOT NULL
        THEN t.bidprice
        ELSE r.bidprice
       END AS bidprice

     , IF(t.timestamp IS NULL, r.askprice, t.askprice)  AS askprice

  FROM profit_loss p
  LEFT
  JOIN trading_price t
    ON t.timestamp = p.timestamp 
   AND t.pairname  = CONCAT(p.fee_unit,p.profit_loss_unit)
  LEFT
  JOIN trading_price r
    ON t.timestamp IS NULL
   AND r.timestamp = p.timestamp
   AND r.pairname  = CONCAT(p.profit_loss_unit,p.fee_unit)
 WHERE ...
 ORDER BY ...

在LEFT JOIN到r中,t.timestamp上的条件将检查我们是否找到了来自t的匹配行。如果我们找到匹配的行,则此条件将评估为FALSE,因此r中的任何行都不会匹配。相反,如果t没有匹配的行,则此条件将评估为TRUE,因此我们将从r返回任何匹配的行。

如果t中有多个匹配的行,则此查询将从p返回该行的多个副本,这是t中每个匹配行的副本。 (如果t中没有匹配的行,那么与r相同的问题。)(我们之所以提到这一点,是因为不能保证不会有超过一个匹配的行。 )

这只是一种方法的例子;还有其他查询模式可以获得相同的结果。

修改

注意:

pt中没有匹配的行时,查询将从r返回一行。如果要求只有在找到匹配的行时才返回p的行,那么我们可以在ORDER BY之前的HAVING子句中处理该条件,该条件测试是否返回了行< / p>

 HAVING (t.pairname IS NOT NULL OR r.pairname IS NOT NULL)

如果我们有保证 askpricebidprice不是NULL,那么我们可以简化SELECT列表中的表达式

     , IFNULL(t.pairname,r.pairname) AS pairname
     , IFNULL(t.bidprice,r.bidprice) AS bidprice
     , IFNULL(t.askprice,r.askprice) AS askprice

我们可以在SELECT列表中使用各种表达式来获得相同的结果。