So I have a table called dash with two columns: value and date.
I have a timestamp variable called localtime.
Both localtime and date are in yyyy-mm-dd hh-mm format.
I need to find the closest timestamp on dash, return the value.
Right now what I have doesn't work.
def convValueChecking(cursor, localtime):
cursor.execute("SELECT Value, MIN(TIMESTAMPDIFF(MINUTE, DATE, %s)) FROM dash", (localtime))
value = cursor.fetchall()
Update:
This one seems to work, the order_date > locatime is very important, otherwise it looks for the smallest negative number
cursor.execute(
"SELECT order_value, order_date FROM dashboard \
WHERE order_date > %s\
ORDER BY ABS(TIMESTAMPDIFF(MINUTE, %s, order_date))\
LIMIT 1", (localtime, localtime,))
Try replacing the SQL string with:
SELECT
value
FROM
dash
WHERE
TIMEDIFF(Date, %s) IN
(
SELECT
MIN(TIMEDIFF(Date, %s))
FROM
dash
)
MySQL syntax means you need to do SELECT then FROM and then declare the WHERE part.
TIMEDIFF works out the difference between two timestamps. TIMESTAMPDIFF works out the difference between two parts of a timestamp (eg between the months, days, seconds etc.). If you want the closest date you should use TIMEDIFF to work out the smallest difference overall.
NB. The words Value and Date also have special properties in MySQL, so you may want to change your column name.
SQLFiddle.
Related
SELECT * FROM table WHERE '2016-03-31' > (SELECT MAX(year) from table where bill_id = 'somevalue')
I am using above query to check if 2016-03-31 is greater than all years present in table against bill_id. It is working fine. but is it correct approach to compare dates. dates will always in above format. Is there any need to convert date format for comparison. value 2016-03-31 will change dynamically but it will be always in Y-m-d format
Note : year is column name which contains full date in Y-m-d format like 2016-05-20
You are not comparing dates. You are comparing a string '2016-03-31' with a number, e.g. 2015.
In order to compare, MySQL silently converts the string to number. One would expect this to crash, as '2016-03-31' certainly isn't a number. MySQL, however, reads from left to right and takes from there all that can be considered a number, i.e. '2016'. Well, one could argue that some people put a minus sign at the end of a number, so this should be '2016-', i.e. -2016. Anyway, MySQL stops before the minus sign, gets 2016 and uses this for the comparision.
I don't know if all this is guaranteed to work in the future. I would not rely on this.
What result would you expect anyway? Is the 31st of March 2016 greater than the year 2016? That's a queer question, don't you think?
Try this. But do you really have a column year that stores only year?
SELECT * FROM table WHERE year(STR_TO_DATE('2016-03-31'))
> (SELECT MAX(year) from table where bill_id = 'somevalue')
SELECT * FROM table WHERE YEAR('2016-03-31') > (SELECT MAX(year) from table where bill_id = 'somevalue')
MySQL YEAR() returns the year for a given date or timestamp. The return value is in the range of 1000 to 9999 or 0 for 'zero' date.
I have table that contains first three columns day, month, year. I have kept it separated instead of making single column date, because this table contains information about subscription analysis. So by keeping separated I can analyze data on daywise. Now I have situation where I want to reset few data. Example like I want to reset data which day, month, year comes between date 2008-01-01 and 2010-10-01. So how can I make where condition in mysql query for separated day, month and year columns?
Please try the following...
WHERE STR_TO_DATE( CONCAT( yearValue,
'-',
monthValue,
'-',
dayValue ) ) BETWEEN '2008-01-01' AND
'2010-10-01'
This clause uses the CONCAT() function to form a string representation of the date being examined, then the STR_TO_DATE() function to convert that string to a DATE value which is then compared to the range specified.
If you have any questions or comments, then please feel free to post a Comment accordingly.
Further Reading
https://dev.mysql.com/doc/refman/5.7/en/comparison-operators.html#operator_between (on MySQL's BETWEEN operator)
https://dev.mysql.com/doc/refman/5.7/en/string-functions.html#function_concat (on MySQL's CONCAT() function)
https://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_str-to-date (on MySQL's STR_TO_DATE() function)
You should really store the value as a date. But you can still do what you want. Here is one way:
where year * 10000 + month * 100 + day between 20080101 and 20101001
Note that values are all integers. A date would be better because the query could take advantage of an index.
You may concatenate your three INT columns with the TO_CHAR function. The transform that into a date using TO_DATE, and then compare.
WHERE TO_DATE(TO_CHAR(year || month || day), 'yyyymmdd') BETWEEN '20080101' AND '20100101';
I have a table with inconsistent date formats. For example:
ID date name
1 01.02.2015 exampleA
2 12.13.2015 exampleB
3 1.11.2015 exampleC
Sometimes the date format is d.m.Y and sometimes the format is m.d.Y. I have created this SQL statement, which transforms the date column of the result in an uniform format:
SELECT IFNULL(DATE_FORMAT(STR_TO_DATE(date, '%d.%m.%Y'), '%d.%m.%Y'),
DATE_FORMAT(STR_TO_DATE(date, '%m.%e.%Y'), '%e.%m.%Y')) AS date,
Name,
ID
FROM `exampleTable`
ORDER BY `date` DESC
But the result is not really ordered by date, because this column is treated like a number or something else, so that the order makes no sense.
What should i do to get the required result?
Is there a way to create a new column and write the date in an
uniform format in my table, so that i can delete the other date
column?
It seems impossible to distinguish programmaticaly the format for the date like 02.03.2015 it can be both %d.%m.%Y and %m.%e.%Y it will give results in both cases though the results will be different. For alike varcahar inputs the information has been lost
I have searched SO for this question and found slightly similar posts but was unable to adapt to my needs.
I have a database with server requests since forever, each one with a timestamp and i'm trying to come up with a query that allows me to create a heatmatrix chart (CCC HeatGrid).
The sql query result must represent the server load grouped by each hour of each weekday.
Like this: Example table
I just need the SQL query, i know how to create the chart.
Thank you,
Those looks like "counts" of rows.
One of the issues is "sparse" data, we can address that later.
To get the day of the week ('Sunday','Monday',etc.) returned, you can use the DATE_FORMAT function. To get those ordered, we need to include an integer value 0 through 6, or 1 through 7. We can use an ORDER BY clause on that expression to get the rows returned in the order we want.
To get the "hour" across the top, we can use expressions in the SELECT list that conditionally increments the count.
Assuming your timestamp column is named ts, and assuming you want to pull all rows from the year 2014, we start with something like this:
SELECT DAYOFWEEK(t.ts)
, DATE_FORMAT(t.ts,'%W')
FROM mytable t
WHERE t.ts >= '2014-01-01'
AND t.ts < '2015-01-01'
GROUP BY DAYOFWEEK(t.ts)
ORDER BY DAYOFWEEK(t.ts)
(I need to check the MySQL documentation, WEEKDAY and DAYOFWEEK are real similar, but we want the one that returns lowest value for Sunday, and highest value for Saturday... i think we want DAYOFWEEK, easy enough to fix later)
The "trick" now is the columns across the top.
We can extract the "hour" from timestamp using the DATE_FORMAT() function, the HOUR() function, or an EXTRACT() function... take your pick.
The expressions we want are going to return a 1 if the timestamp is in the specified hour, and a zero otherwise. Then, we can use a SUM() aggregate to count up the 1. A boolean expression returns a value of 1 for TRUE and 0 for FALSE.
, SUM( HOUR(t.ts)=0 ) AS `h0`
, SUM( HOUR(t.ts)=1 ) AS `h1`
, SUM( HOUR(t.ts)=2 ) AS `h2`
, '...'
, SUM( HOUR(t.ts)=22 ) AS `h22`
, SUM( HOUR(t.ts)=23 ) AS `h23`
A boolean expression can also evaluate to NULL, but since we have a predicate (i.e. condition in the WHERE clause) that ensures us that ts can't be NULL, that won't be an issue.
The other issue we can encounter (as I mentioned earlier) is "sparse" data. To illustrate that, consider what happens (with our query) if there are no rows that have a ts value for a Monday. What happens is that we don't get a row in the resultset for Monday. If it does happen that a row is "missing" for Monday (or any day of the week), we do know that all of the hourly counts across the "missing" Monday row would all be zero.
I'm using a MySQL query to pull a range of datetimes as a Unix Timestamp (because I'll be converting them to Javascript time). I'm grouping by 'FROM_UNIXTIME' as below:
SELECT
UNIX_TIMESTAMP(DateAndTime) as x,
Sum(If(Pass='Pass',1,0)) AS y,
Sum(If(Pass='Fail',1,0)) AS z,
Sum(If(Pass='Fail',1,0))/(Sum(If(Pass='Pass',1,0))+Sum(If(Pass='Fail',1,0))) AS a,
cases.primaryApp
FROM casehistory, cases
WHERE DATE_SUB(CURDATE(),INTERVAL 80 DAY) <= DateAndTime
AND cases.caseNumber = casehistory.caseNumber
AND cases.primaryApp = 'Promo'
GROUP BY FROM_UNIXTIME(x, '%Y-%m-%d')
While I'd expected my timestamps to be returnd evenly spaced (that is, same amount of time between each day/group), I get the following series:
1300488140, 1300501520,
1300625099, 1300699980
All the other data from the query is correct, but because the spacing of the timestamps is irregular, a bar chart based on these stamps looks pretty awful. Perhaps I'm doing something wrong in the way I apply the grouping?
Thank you for the reply. My query 'made sense' in that it produced that could be plotted (the grouping was done on the x alias for the dateandtime value), but the problem was that pulling a Unix timestamp from the database and grouping by day returned a series of timestamps that did not have equal distance between them.
I solved this by pulling only the day (without the time) from the datetime MySQL field, then - in PHP - concatenating an empty time to the date, converting the resulting string to a time, then multiplying the whole shebang by 1000 to return the Javascript time I needed for the charting, like this:
x = x . ' 00:00:00';
x = strtotime(x) * 1000;
The answer put me on the right track; I'll accept it. My chart looks perfect now.
Question is very confused.
Your SQL statement makes no sense - you are grouping by entities not found in the select statement. And a bar chart plots an ordered set of values - so if there's something funny with the spacing then its not really a bar chart.
But I think the answer you are looking for is:
SELECT DATE_FORMAT(dateandtime, '%Y-%m-%d') as ondate
, SUM(IF(Pass='Pass',1,0)) AS passed
, SUM(IF(Pass='Fail',1,0)) AS failed
, SUM(IF(Pass='Fail',1,0))
/(SUM(IF(pass='Pass',1,0))+SUM(IF(Pass='Fail',1,0))) AS fail_pct
, cases.primaryapp
FROM casehistory, cases
WHERE DATE_SUB(CURDATE(),INTERVAL 80 DAY) <= dateandtime
AND cases.casenumber = casehistory.casenumber
AND cases.primaryapp = 'Promo'
GROUP BY DATE_FORMAT(dateandtime, '%Y-%m-%d')
ORDER BY 1;
And if you need Unix timestamps, wrap the above in....
SELECT UNIX_TIMESTAMP(STR_TO_DATE(CONCAT(ilv.ondate, ' 00:00:00'))) AS tstamp
, passed
, failed
, fail_pct
, primaryapp
FROM (
...
) AS ilv
Note that you'll still get anomolies around DST switches.
C.