MySQL group by TimeStamp - mysql

I am writing a Python code where I need to use MySQLdb to retrieve data from a MySQL database. A part of the original database looks like this:
I used this command
SELECT TimeStamp,Pac
FROM SolarData
WHERE DATE(`TimeStamp`) = CURDATE()
GROUP BY HOUR(TimeStamp);
to group the data by hour, but the result is not what i expected:
The Pac number shown for every hour is the same number as the first record of each hour. It's not an accumulated number for the whole hour. What I need is an accumulated number of the whole hour.

That's because MySQL is like your alcoholic uncle when you don't use GROUP BY by the ANSI standard. You probably want:
SELECT HOUR(TimeStamp) AS Hour,
SUM(Pac) AS Pac
FROM SolarData
WHERE `TimeStamp` >= CURDATE()
AND `TimeStamp` < CURDATE() + INTERVAL 1 DAY
GROUP BY HOUR(TimeStamp);
It would be helpful to see the desired result you're looking for. Until then, the above query is just a guess based on group the data by hour. For future reference, use SQL Fiddle to post your table structure/data.

"How do I decorate the code so that the hour format can have the date on it as well like this 2014-01-14 07:00"
All of Hour belong to today (CURDATE()), and second part is always ':00', so following query might help you. Could try this?
SELECT CONCAT(CURDATE(), ' ', Hour, ':00'), Pac
FROM (
SELECT HOUR(TimeStamp) AS Hour,
SUM(Pac) AS Pac
FROM SolarData
WHERE DATE(`TimeStamp`) = CURDATE()
GROUP BY HOUR(TimeStamp)
) x;

Related

TRICKY Rolling Sum Query with Reset

Assuming that there are 6 months of historical data with hundreds of rides per day:
Write a query that returns, for each of the last 90 days, a count of the rides taken in the 7 day window preceding that day
I would like to find a way to write this in MySQL but have had some trouble with having a rolling sum that resets along with how I could cut up timestamps to reflect a day of the year/date and to then group by that.
I have tried writing subqueries that will limit the sum to a week prior and then place an additional limit of 90 days after that but cannot seem to get the code to return any output.
I have tried writing this is PostgreSQL using a sort of "window" functionality but am much more comfortable working in MySQL and would like to be able to solve it that way. I am familiar on how to write limits, group and order among other things but I am having trouble with the rolling sum resetting per week.
Thank you for your help!
First you'll want a numbers table/query. There are some tricky CTE ways to do that but it might be easier for now just to add a table with the numbers 1-90 in 90 rows.
Then use that to generate, for each row, a date range. Sorry if the syntax isn't quite correct, but write a query along the lines:
SELECT num, DATE_ADD(CURRENT_DATE(), INTERVAL -(num+7) DAY) startdate, DATE_ADD(CURRENT_DATE(), INTERVAL -num DAY) enddate FROM numbers
Then you can cross-join that with your rides table grouped on num and counting the rows in the range:
SELECT num, startdate, enddate, SUM(CASE WHEN startdate <= ridedate AND ridedate <=
enddate THEN 1 ELSE 0 END) ridecount
FROM (date range query) dts, rides
GROUP BY dts.num
Hope that helps.
Assuming you have data on each day, a correlated subquery might be simplest approach:
select dt,
(select count(*)
from rides r
where r.ridedate >= d.dte - interval 7 day and
r.ridedate < d.date
) as rolling_7
from (select distinct ridedate as dt
from rides
) dt

Select rows from yesterday's date

I have a query function that selects all rows from the previous days. However, I need it to only select the rows with yesterdays date but am unsure how to include just the previous day.
My current query is:
SELECT pdate FROM table 1
WHERE pdate < Date(NOW()) + INTERVAL 1 DAY
I would imagine it would look something like this, which has the advantage of using indexes (if you have them implemented)
SELECT pdate FROM table 1
WHERE pdate >= Date(NOW()) - INTERVAL 1 DAY
AND pdate < Date(NOW())
You can use the DATE_SUB() function to get yesterday's date, and then use a WHERE clause condition to look for just that date, like this:
SELECT *
FROM myTable
WHERE DATE(pDate) = DATE_SUB(pDate, INTERVAL 1 DAY);
Here is a list of MySQL's Date and Time Functions which may help you.
NOTE: This will work, but because you are using a function on the pDate column in the where clause this will not be able to take advantage of any indexes you have (see comments below). Brian Driscoll has given an answer that will work better. I am choosing to leave this answer because while it is less efficient, I believe it is more readable as the where clause is very explicit in what it is checking and is slightly more readable. Whether or not the trade off is worth it here is up to the developer.

Select MySQL data starting from a specific date

I have player statistics which I would like to publish from certain dates.
At the moment I can see statistics in the database from the beginning.
SELECT name,
bankmoney AS Bank,
Playerkills AS 'Player Kills',
deathcount AS Deaths ,
aikills AS 'AI Kills',
teamkills AS 'Team Kills',
revivecount AS Revives ,
capturecount AS 'Territories Captured',
LastModified AS 'Last Seen'
FROM playerinfo
JOIN playerstats
ON playerinfo.UID = playerstats.PlayerUID
ORDER BY BankMoney DESC;
But I would like to present statistics from the start of the day and the start of the week.
How would I do that ?
Based on Spitfire's comments, to get the last 24 hours of data you can use INTERVAL and go back the required number of days you want. NOW() will give you the time the query was executed and BETWEEN will allow you to search between two days. So that part of the query could be:
WHERE 'Last Seen' BETWEEN NOW() AND NOW() - INTERVAL 1 DAY;
A week would require a change from 1 day to 7.
Try it.SELECT * from table_name where a.exam_date BETWEEN $date1 AND $date2;
for example if you want to see only statistics with lastModified greater or equal today just add a where clause:
WHERE 'Last Seen' >= CURRENT_DATE()

SQL Query for reservation dates that break a month end?

I'm using a custom PHP function to produce a visual calendar for a single month that blocks out dates based on a table that contains an start date, and an duration - For example:
...This is produced by data saying that the table should be blocked out for 4 days from the 14th, and 7 days from the 27th.
The query looks something like this:
SELECT GROUP_CONCAT(DATE_FORMAT(start_date,'%d'),':', event_duration) AS info
FROM events
WHERE YEAR(start_date = '2012'
AND MONTH(start_date) = '07'
ORDER BY start_date
(You could safely ignore the group concat and return the data as individual rows, that doesn't really matter).
I'm looking for a modification to the query that would block out dates at the start of the month IF an event starts in the previous month, but its length takes it into the following.
For instance - in the above example, the event on the 27th is actually scheduled to last 7 days in the database, so if I ran the query for MONTH(start_date) = '08' I'd like to say the first two dates blocked out, which they wouldn't currently be, because the start date that would block it out is not in the month being selected.
I'm fairly sure there's a subquery or something in there to grab the rows, but I just can't think of it. Any takers?
EDIT
The answer from Salman below pointed me in the directon I wanted to go, and I came up with this as a way of getting carryovers from the previous month to show as '1st' of the month with the number of remaining days:
SELECT IF(MONTH(start_date) < '08', '2012-08-01', start_date) AS starter,
IF(MONTH(start_date) < '08', duration - DATEDIFF('2012-08-01',start_date), duration) AS duration
FROM EVENTS
WHERE YEAR(start_date) = '2012'
AND (MONTH(start_date) = '08' OR MONTH(start_date + INTERVAL duration DAY) = '08')
Obviously a lot of variables there to replace in PHP, so maybe there's an even better way?
Original Answer:
Assuming that the month in question is 2012-07, you need this query:
SELECT column1, column2, columnN
FROM `events`
WHERE `start_date` <= '2012-07-01'
AND `start_date` + INTERVAL `duration` DAY > '2012-07-01'
ORDER BY start_date
Revised Answer:
Apparently you need a query that checks for overlapping (or conflicting) dates. The example dates are 2012-07-01 through 2012-08-01 and the query is:
SELECT *
FROM events
WHERE '2012-08-01' > start_date
AND start_date + INTERVAL duration DAY > '2012-07-01'
ORDER BY start_date
To constrain the start date and interval, you can use SELECT ... CASE statement:
SELECT
CASE
WHEN start_date < '2012-07-01' THEN '2012-07-01'
ELSE start_date
END AS start_date_copy,
CASE
WHEN start_date < '2012-07-01' THEN duration - DATEDIFF('2012-07-01', start_date)
ELSE duration
END AS duration_copy,
FROM ...
The answer I was looking for, thanks to the other contributor for pointing me in the right direction and enabling me to solve it!
This is based on $yyyy and $mm coming from PHP (in my case, into a function call), and selecting individual rows rather than grouping:
SELECT start_date, duration
FROM reservations
WHERE YEAR(start_date) = '".$yyyy."'
AND MONTH(start_date) = '".$mm."'
UNION
SELECT '".$yyyy."-".$mm."-01',
duration - DATEDIFF('".$yyyy."-".$mm."-01',start_date)
FROM reservations
WHERE YEAR(start_date) = '".$yyyy."'
AND MONTH(start_date) < '".$mm."'
AND MONTH(start_date + INTERVAL duration DAY) = '".$mm."'
ORDER BY start_date

how to cast a datetime to a specific 24 hour time

I have all my data stamped with a field- dated which is in the format Y-m-d H:i- i would like to cast this field using mysql to represent the hour of the day so- 2011-11-21 15:28:05 would become 15- i have been reading the docs but it doesnt state whether or not you can specify a format
is this possible?
The idea is, I can count how many rows are stamped for each hour then display this in a graph.
this has been my working so far
SELECT CAST(dated AS TIME) FROM `posts` WHERE CAST(dated AS DATE) = CAST('".$start_date."' as DATE) AND type = '' ORDER by dated ASC;
Use date_format:
SELECT count(*), date_format(dated, "%Y:%m:%d %H") AS hour
FROM posts
GROUP BY hour
Or to get just the hour, regardless of day:
SELECT count(*), HOUR(dated) AS hour
FROM posts
GROUP BY hour
You can simply use HOUR() function to get the hour