MySQL - select distinct values against a range of columns

大憨熊 提交于 2019-12-12 06:36:28

问题


The following table will store exchange rates between various currencies over time:

CREATE TABLE `currency_exchange` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `currency_from` int(11) DEFAULT NULL,
 `currency_to` int(11) DEFAULT NULL,
 `rate_in` decimal(12,4) DEFAULT NULL,
 `rate_out` decimal(12,4) DEFAULT NULL,
 `exchange_date` datetime DEFAULT NULL,
 PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci

How would I query it to fetch a list the most recent exchange rates?

It'd essentially be identifying the combined currency_from and currency_to columns as a distinct exchange rate, then finding the one with the most recent date.

For example, let's say I've got the data as:

INSERT INTO currency_exchange (id, currency_from, currency_to, rate_in, rate_out, exchange_date) VALUES
(1, 1, 2, 0.234, 1.789, '2012-07-23 09:24:34'),
(2, 2, 1, 0.234, 1.789, '2012-07-24 09:24:34'),
(3, 2, 1, 0.234, 1.789, '2012-07-24 09:24:35'),
(4, 1, 3, 0.234, 1.789, '2012-07-24 09:24:34');

I'd want it to select row ID's:

  • 1 - as the most recent rate between currencies 1 and 2
  • 3 - as the most recent rate between currencies 2 and 1
  • 4 - as the most recent rate between currencies 1 and 3

回答1:


The following query should work:

SELECT ce.*
FROM currency_exhcnage ce
LEFT JOIN currency_exchange newer
    ON (newer.currency_from = ce.currency_from
    AND newer.currency_to = ce.currency_to
    AND newer.exchange_date > ce.exchange_date)
WHERE newer.id IS NULL

The trick of doing a self-LEFT JOIN is to avoid resorting to a subquery that may be very expensive if you have large datasets. It's essentially looking for records where no "newer" record exists.

Alternatively, you could go for a simpler (although it may (or may not, as noted in comments) be slower):

SELECT *
FROM currency_exchange ce
NATURAL JOIN (
    SELECT currency_from, currency_to, MAX(exchange_date) AS exchange_date
    FROM currency_exchange
    GROUP BY currency_from, currency_to
) AS most_recent



回答2:


Insert the values of $currency_from and $currency_to in your dynamic query. The query below will return the nearest row to the current time

SELECT id FROM currency_exchange WHERE currency_from='$currency_from' AND currency_to='$currency_to' ORDER BY ABS( DATEDIFF( exchange_date, now() ) ) LIMIT 1 


来源:https://stackoverflow.com/questions/11614966/mysql-select-distinct-values-against-a-range-of-columns

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!