Question

Good evening,

wanted to write a MySQL which compares the latest value ('Close') of a group three days ago to the latest value of today for the same group. This was not the problem, it works. But it doesn't sort by date. Every new entry got a timestamp and, as I stated already, I want the latest entry of a day.

SELECT p1.ticker, p1.date, p1.close, p1.close - p2.close
FROM prices AS p1
LEFT JOIN prices AS p2 ON p1.ticker = p2.ticker
WHERE DATE( p2.DATE ) = CURDATE( ) -3
AND DATE( p1.DATE ) = CURDATE( ) 
GROUP BY p1.ticker
ORDER BY p1.DATE DESC , p2.Date DESC 

You see I use Curdate, but I tried Current_Timestamp, too. The result of p1.close - p2.close shows that SQL took the wrong entry. Wrong = not the latest one. If you can help, thank you.

--- Edit --- Example Data

CREATE TABLE prices (
  ticker varchar(15) DEFAULT NULL,
  `Date` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
  `Close` decimal(24,4) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

--
-- Data for table 'prices'
--

INSERT INTO prices (ticker, Date, Close) VALUES
('FB', '2014-04-01 16:24:29', 22.0000),
('FB', '2014-04-01 16:24:38', 23.0000),
('FB', '2014-04-04 15:09:46', 33.0000),
('FB', '2014-04-04 15:09:52', 36.0000),
('FB', '2014-04-04 20:09:42', 72.0000),
('FB', '2014-04-04 20:09:31', 61.0000),
('FB', '2014-04-04 20:09:19', 57.2500),
('FB', '2014-04-04 20:09:13', 57.0000),
('FB', '2014-04-04 20:09:06', 56.0000),
('FB', '2014-04-04 20:08:37', 52.2300),
('FB', '2014-04-04 20:08:25', 55.0000),
('FB', '2014-04-04 20:08:05', 65.0000),
('FB', '2014-04-04 20:07:54', 77.0000),
('FB', '2014-04-04 20:08:00', 71.0000),
('FB', '2014-04-04 20:09:48', 69.0000),
('FB', '2014-04-04 20:09:53', 66.0000),
('FB', '2014-04-04 20:09:59', 62.0000),
('FB', '2014-04-04 20:10:05', 63.0000),
('FB', '2014-04-04 20:10:15', 42.0000),
('FB', '2014-04-04 20:10:21', 39.0000),
('FB', '2014-04-04 20:10:28', 27.0000),
('FB', '2014-04-04 20:10:40', 32.0000),
('FB', '2014-04-04 20:10:45', 33.0000),
('FB', '2014-04-04 20:10:49', 32.0000),
('FB', '2014-04-04 20:10:55', 29.0000),
('FB', '2014-04-04 20:10:59', 24.0000),
('FB', '2014-04-04 20:11:06', 19.0000),
('FB', '2014-04-04 20:11:11', 18.0000),
('FB', '2014-04-04 20:11:16', 19.0000),
('FB', '2014-04-04 20:11:21', 22.0000),
('FB', '2014-04-04 20:11:26', 16.0000),
('FB', '2014-04-04 20:11:38', 11.0000),
('FB', '2014-04-04 20:11:43', 22.0000),
('FB', '2014-04-04 20:11:48', 66.0000),
('TSLA', '2014-04-01 23:10:52', 72.0000),
('TSLA', '2014-04-04 23:11:00', 62.0000);

Desired Output should be

FB 66.0000 43
TSLA 62.0000 -10
Was it helpful?

Solution

You need another self join for the maximum date

SELECT p1.ticker, p1.date, p1.close, p2.close c1,p1.close - p2.close
FROM prices AS p1
 JOIN 
(SELECT ticker,MAX(date) date 
 FROM prices 
 WHERE DATE(DATE ) = CURDATE( ) 
 GROUP BY ticker)
pr1 USING(date,ticker)
LEFT JOIN prices AS p2 ON p1.ticker = p2.ticker
WHERE DATE( p2.DATE ) = CURDATE( ) -3
GROUP BY p1.ticker
ORDER BY p1.DATE DESC , p2.Date DESC ;

For FB group the difference will be 44 not 43 because from current date - 3 days the minimum close entry is 22 so the latest close entry for today is 66 and - 22 will be 44 not 43

Fiddle Demo

For more optimal results to exactly pick the oldest close entry for last three days you can do so

SELECT p1.ticker, p1.date, p1.close, p2.close c1,p1.close - p2.close
FROM prices AS p1
 JOIN 
(SELECT ticker,MAX(date) date 
 FROM prices 
 WHERE DATE(DATE ) = CURDATE( ) 
 GROUP BY ticker) pr1 USING(date,ticker)
LEFT JOIN prices AS p2 ON p1.ticker = p2.ticker
JOIN 
(SELECT ticker,MIN(date) date 
 FROM prices 
 WHERE DATE(DATE) = CURDATE() -3
 GROUP BY ticker) pr2 
ON(pr2.date=p2.date AND pr2.ticker=p2.ticker)
ORDER BY p1.DATE DESC , p2.Date DESC ;

Fiddle Demo

OTHER TIPS

your date maybe its a string. try that:

ORDER BY STR_TO_DATE(p1.DATE,'%Y-%m-%d %H:%m:%s') DESC,STR_TO_DATE(p2.DATE,'%Y-%m-%d %H:%m:%s') DESC 

you can do them separately with a limit to get the correct result see FIDDLE

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top