mysql max(date) not working - mysql

So i have this query that is supposed to return some information like price, open, close, etc.. for the LATEST entry.
SELECT * FROM History WHERE symbol = $symbol Having max(`date`);
But for whatever reason its not returning the correct information. It for some reason believes that the max date is 2013-02-14, but if i look at all the data the most recent is actually 2013-02-27.
in this particular case
$symbol = "AGNC"
Does the max function not work on date?

I think you want to have something like this. I'm not fan of doing this using ORDER BY clause because there are some possibilities (although much little) that records may have the same latest date entry.
SELECT *
FROM History
WHERE symbol = $symbol AND
date = (SELECT MAX(date) FROM History)
SQLFiddle Demo

My suggestion would be not using MAX at all; if what you want to do is only fetching the latest entry in the table, you could try:
SELECT * FROM History WHERE symbol = $symbol ORDER BY date DESC LIMIT 1;
This works perfectly as long as your date field is actually declared as a date-related MySQL field type, like date, datetime, etc.
As JW pointed out in his answer, you may want to add more fields in your ORDER BY statement to disambiguate records that have the exact same date.
Also, you may want to put $symbol in quotes if that's a string field (char, varchar, etc):
SELECT * FROM History WHERE symbol = '$symbol' ORDER BY date DESC LIMIT 1;
Cheers!

The following should do what you want:
SELECT *
FROM History h
WHERE symbol = $symbol and
`date` = (select max(`date`) from History where symbol = $symbol)

You may use alias table name:
SELECT *
FROM History
WHERE symbol = $symbol AND
date = (SELECT MAX(date) FROM History);

Related

Mysql subquery or something better

I am somewhat new to mysql and I am having an issue on how I should best write the following query. Say I have a table that has a datetime column as well as a few others I want to search on. Since this is just one table, I don't think a join statement would be appropriate here (but I may be wrong since I have not done much in the way of join statements) and I think a subquery is what I need here. So my initial query is to search the table based on a search string the user entered and then I want to limit that on a datetime (start date and end date) also specified by the user in an HTML form.
Table Schema
id, datetime, host, level, message
I want to select any rows that contain $searchstring first so something like ...
SELECT * FROM $table WHERE (level LIKE '%$searchstring%') OR (message LIKE '%$searchstring%') LIMIT $offset,$limit
If I want to limit the above results also by the datetime column, the query would look something like this ...
SELECT * FROM $table WHERE (datetime >='$startdate') AND (datetime < '$enddate')
How can I best merge these queries into one so I can first get any rows that match the search query and then further limit the rows by the start and end datetime?
TIA
You can achieve that by using a single where condition.
In your case:
SELECT * FROM $table WHERE ((level LIKE '%$searchstring%') OR (message LIKE '%$searchstring%')) AND (datetime >='$startdate') AND (datetime < '$enddate') LIMIT $offset,$limit
You don't have to use a JOIN but only add a condition
SELECT *
FROM $table
WHERE (level LIKE '%$searchstring%' OR message LIKE '%$searchstring%')
AND
datetime >='$startdate'
AND datetime < '$enddate'
LIMIT $offset,$limit

order by date and select until specific id is reached

I have a simple table with ID, STATUS, DATE columns, the rows in the table are ordered by DATE, I want to get all the rows until a specific ID is reached, and then stop, something like:
SELECT FROM myTable WHERE `DATE` <= '2017-10-09' ORDER BY `DATE` ASC UNTIL? `ID` = 119;
I like to know if that is possible somehow, to stop on a specific ID, whatever the ID was..
Thanks.
EDIT EXPLAINING
I want to select rows that are ordered under any column, but stop when a specific provided ID is reached. in the above image the result should be all the rows except the ones below the row 119.
I hope it's clear now.
Something like this might work:
SET #marker = NULL;
SELECT *
FROM myTable
WHERE `DATE` <= '2017-10-09'
AND ISNULL(#marker := IF(id = 119, 1, #marker))
ORDER BY `DATE` ASC;
You should phrase the query to select records whose date is less than the date of the record for which ID = 119:
SELECT *
FROM myTable
WHERE DATE <= (SELECT DATE FROM myTable WHERE ID = 119);
Tim Biegeleisen's answer is correct, but if you have no time in your date field then the order by is going to use the date and then any ordered indexes you have specified. So you will get all of the records back that equal the date of the id specified in the subquery's WHERE clause.
So for example, you are going to also return the rows for ids 200-202, no way around that unless you provide more precision on your date OR add the id field to your order by clause, in which case you'll need to be comfortable excluding all IDs above the specified ids integer value for the same date.

Excluding first and last result from sql query

I'm fairly new to SQL so this may be fairly simple but I'm trying to write a script in SQL that will allow me to get a set of data but I don't want the first or last result in the query. I can find lots on how to remove the first result and how to remove the last result but not both.
This is my query so far:
SELECT * FROM itinerary Where ID = 'A1234' ORDER BY DateTime ASC
I want to remove the first and the last record of that select based on the DateTime.
This may not be the most performant way to do this, but you didn't give any schema info, and it looks like your ID column is not unique. It would be easier if you had a primary key to work with.
SELECT * FROM itinerary
WHERE ID = 'A1234'
AND DateTime <
(SELECT MAX(DateTime) FROM itinerary WHERE ID = 'A1234')
AND DateTime >
(SELECT MIN(DateTime) FROM itinerary WHERE ID = 'A1234')
ORDER BY DateTime ASC
This will basically select every record where the ID is A1234 and the DateTime doesn't equal the max or min datetime. Please note, if you have multiple records with the same value for DateTime and that also happens to be the min or max value, you might exclude more than just the first or last.
This might be good enough though. If not, you might need to write a stored procedure and not just straight ANSI SQL.
Try this ..
select * from
(select a.*,row_number() over (partition by DateTime order by DateTime desc) as rnm
from itinerary Where ID = 'A1234')x
where rm <> 1 and rm not in (
select max(rm) from
(
select row_number() over (partition by DateTime order by DateTime desc) as rnm
from itinerary Where ID = 'A1234'))
Select in reverse order & skip first and then select in the required order from the result, skipping first.
SELECT * FROM (SELECT *
FROM itinerary
Where ID = 'A1234'
ORDER BY DateTime DESC
LIMIT 1, 18446744073709551615) x ORDER BY DateTime ASC
LIMIT 1, 18446744073709551615
18446744073709551615 is max integer just in case you wanted to know why I picked that value

Querying Where date_created without time is same as last_updated without time

In MySQL, I need to write a query (if possible) that finds all rows of a table where the date_created is the same as last_updated. The rub is that I need to ignore the time. Basically, I'm looking for user rows that were created and activated the same day (we don't store an activation date). So presumably the dates would be the same but the times may be different.
You could use the DATE() function, which returns only the date portion of a datetime value. This allows you to compare just the date portion of the values:
SELECT * FROM table_name
WHERE DATE(date_created) = DATE(last_updated)
The timezone may be relevant here. So you may want to cast the datetime values to the user's timezone prior to using the DATE() function, using CONVERT_TZ().
Try this:
SELECT *
FROM table_name
WHERE DATE_FORMAT(date_created, '%Y-%m-%d') = DATE_FORMAT(last_updated, '%Y-%m-%d')
not pretty but works:
SELECT *
FROM table_name
WHERE day(date_created) = day(last_updated) and
month(date_created) = month(last_updated) and
year(date_created) = year(last_updated)

MySQL Running Total with COUNT

I'm aware of the set #running_sum=0; #running_sum:=#running_sum + ... method, however, it does not seem to be working in my case.
My query:
SELECT DISTINCT(date), COUNT(*) AS count
FROM table1
WHERE date > '2011-09-29' AND applicationid = '123'
GROUP BY date ORDER BY date
The result gives me unique dates, with the count of occurrences of application 123.
I want to keep a running total of the count, to see the accumulated growth.
Right now I'm doing this in PHP, but I want to switch it all to MySQL.
Using the method from the first line of this post simply duplicates the count, instead of accumulating it.
What am I missing?
P.S. The set is very small, only about 100 entries.
Edit: you're right ypercube:
Here's the version with running_sum:
SET #running_sum=0;
SELECT date, #running_sum:=#running_sum + COUNT(*) AS total FROM table1
WHERE date > '2011-09-29' AND applicationid = '123'
GROUP BY date ORDER BY date
count column ends up being the same as if I just printed COUNT(*)
Updated Answer
The OP asked for a single-query approach, so as not to have to SET a user variable separately from using the variable to compute the running total:
SELECT d.date,
#running_sum:=#running_sum + d.count AS running
FROM ( SELECT date, COUNT(*) AS `count`
FROM table1
WHERE date > '2011-09-29' AND applicationid = '123'
GROUP BY date
ORDER BY date ) d
JOIN (SELECT #running_sum := 0 AS dummy) dummy;
"Inline initialization" of user variables is useful for simulating other analytic functions, too. Indeed I learned this technique from answers like this one.
Original Answer
You need to introduce an enclosing query to tabulate the #running_sum over your COUNT(*)ed records:
SET #running_sum=0;
SELECT d.date,
#running_sum:=#running_sum + d.count AS running
FROM ( SELECT date, COUNT(*) AS `count`
FROM table1
WHERE date > '2011-09-29' AND applicationid = '123'
GROUP BY date
ORDER BY date ) d;
See also this answer.
SQL is notoriously poor at running totals. As your result set is in order, you are much better advised to append a calculated running total column on the client side. Nothing in SQL will be as performant as that.
The Running total can be easily calculated using the lib_mysqludf_ta UDF library.
https://github.com/mysqludf/lib_mysqludf_ta#readme