I have a site where the client stores event info into a database... really simple.
the issue is when I want to get the data out. I can currently do so by selecting all data and ordering it by the month asending....
What I need is for it to display all the info as it does now, except it needs to display this info by listing all data for the current month first then the next month and so on. I dont care if I have to just simply list the info in proper ascending monthly oder and just make it scroll to the current months first event....
Currently I have the following for my db.
ID, year, month, day, event_loc, event_address, event_link, event_time, event_name
you can see it in action here:
http://www.michael-eubanks.com/events.php
Maybe a SQL like this:
select * from <tablename> order by year desc, month desc, day desc
It will order the data first by year, then by month, then by day, all in descending order, and hence you should see the most recent event first, and so forth.
if I am correct, the thing you want is grouping(aggrigation), so all you need is group by:
SELECT * FROM myTable GROUP BY month ORDER BY month DESC;
and I used descending, to display the current month first.
If I understand correctly and you want to select only events starting from the first day of the current month then you can do it like this
SELECT ID, year, month, day, event_loc, event_address, event_link, event_time, event_name
FROM events
WHERE STR_TO_DATE(CONCAT_WS('-', year, month, day), '%Y-%c-%e') >= DATE_FORMAT((CURDATE()), '%Y-%m-01')
ORDER BY year, month, day
Here is SQLFiddle demo
Now, to be able to normally query your data using indices and range searches I'd suggest to change your table's schema to utilize datetime (for event_date column) and time (for event_duration) data types. Proposed schema might look like this
CREATE TABLE events
(`ID` int,
`event_date` datetime,
`event_loc` varchar(256),
`event_address` varchar(256),
`event_link` varchar(256),
`event_duration` time,
`event_name` varchar(256)
);
Then the query would look like
SELECT ID, DATE(event_date) event_date,
event_loc,
event_address,
event_link,
CONCAT(DATE_FORMAT(event_date, '%l:%i%p - '),
DATE_FORMAT(ADDTIME(event_date, event_duration), '%l:%i%p')) event_timee,
event_name
FROM events
WHERE event_date >= DATE_FORMAT(CURDATE(), '%Y-%m-01')
ORDER BY event_date
Here is SQLFiddle demo
Related
I am using Google Big Query and I am trying to to sum the data from each month (which was given on a daily basis).
SELECT sum(EXTRACT(MONTH FROM date)) as month, region_name, avg(stringency_index) as stringency_index, sum(deaths) as deaths FROM `bigquery-public-data.covid19_govt_response.oxford_policy_tracker`
WHERE (stringency_index is not null) and (region_name = "New York" OR region_name = "Florida") AND (date BETWEEN '2020-05-01' AND '2020-12-30')
GROUP BY region_name, date
ORDER BY EXTRACT(MONTH FROM date);
But it still is showing 30ish rows for each month, making me believe that it isn't summing the months, but still giving me the data by data. Would I use a TRUNC function? The problem is the column label for date in this dataset is date, so I don't know how to TRUNC(MONTH as date) if date is both a column name and a variable.
Any help is appreciated.
Thank you,
Yoni
First, I would recommend truncating the date. Then:
SELECT date_trunc(date, month) as month, region_name,
avg(stringency_index) as stringency_index,
sum(deaths) as deaths
FROM `bigquery-public-data.covid19_govt_response.oxford_policy_tracker`
WHERE stringency_index is not null and
region_name IN ('New York', 'Florida') AND
date BETWEEN '2020-05-01' AND '2020-12-30'
GROUP BY region_name, month
ORDER BY month;
The problem with your query is that you are aggregating by date. You could fix it by aggregating by month; I think the complete date is safer -- although COVID data has not yet existed for an entire year, so right now, you don't have to worry about data from months in different years.
Goal: Write the correct SQL to solve the problems below.
Part 1:
Having trouble figuring out the SQL statement on how to get the timestamp that includes the date and the hour where you have the maximum "in_bytes" for each day. See "video_hourly" table DDL code below. If there are two maximum values that have the same value in a given day just pick the first one. This data is being graphed in highcharts so there can only be one data point for each given day. You can fill the table with some sample data.
Part 2:
Another part of this problem is once you have all of the unique maximum "in_bytes" for each day then you need to sum the "in_bytes" and "out_bytes" to get one record.
To convert the UTC time from the database to local time we using this in the queries:
SELECT time_stamp,CONVERT_TZ(time_stamp, '+00:00', '-07:00' ) as localtime
Here is the DDL SQL for the table:
CREATE TABLE video_hourly (
id bigint(20) NOT NULL AUTO_INCREMENT,
time_stamp datetime NOT NULL,
in_bytes bigint(20) UNSIGNED NOT NULL DEFAULT 0,
out_bytes bigint(20) UNSIGNED NOT NULL DEFAULT 0,
opt_pct decimal(11, 2) NOT NULL DEFAULT 0.00,
PRIMARY KEY (id)
)
ENGINE = INNODB;
Any help or advice on this would greatly be appreciated. Thank you!
See this list of datetime functions that you can use. Specifically, you can use HOUR() to get the hour value.
You can also use DATE() to get the date part of a datetime column. Once you have those, you can group them together. I will try and break it down for you.
This will return the date, hour, and the in_bytes for that hour, by grouping by day and hour.
SELECT DATE(time_stamp) AS date, HOUR(time_stamp) AS hour, SUM(in_bytes) AS totalInBytes
FROM video_hourly
GROUP BY date, hour
ORDER BY date, hour, totalInBytes DESC;
This will also but the max totalInBytes at the top of each group because it orders by that in descending order.
Also, please see this question for how to get the max value in a group, which in this case is you want to get the max inBytes for each date.
Then, you can change your query to this:
SELECT CONCAT(v.date, ' ', v.hour) AS dateAndHour, v.totalInBytes
FROM(SELECT time_stamp AS fullDate, DATE(time_stamp) AS date, HOUR(time_stamp) AS hour, SUM(in_bytes) AS totalInBytes
FROM video_hourly
GROUP BY date, hour
ORDER BY date, hour, totalInBytes DESC
) v
WHERE(
SELECT COUNT(*)
FROM(SELECT DATE(time_stamp) AS date, HOUR(time_stamp) AS hour, SUM(in_bytes) AS totalInBytes
FROM video_hourly
GROUP BY date, hour
ORDER BY date, hour, totalInBytes DESC
) vh
WHERE vh.date = v.date AND vh.totalInBytes >= v.totalInBytes
) <= 1;
I can't try it without any sample data, but here is an SQL Fiddle link, if you want to try it out. I used this to make sure it would not produce any errors.
Say I have a table with two columns
TimeStamp of type TIMESTAMP
A of type FLOAT
This table is created and updated by an external application, so inserts and updates are outside of my control. The table design can't be altered in any way.
What I need to do is select each entry closest to and before 10AM for each day during the entire past month.
Thanks in advance.
The inner pre-query should get on a per year/month basis, prior to the month you are currently in. This is forced by a SQLVariable created by the formatted 'YYYY-MM-01' date, such as today... 2012-03-19, keep just year/month but force 01. This also implies timestamp of 12:00:00 am (midnight). The NEXT # variable is to determine the first of the month PRIOR to the one just computed... thus 2012-02-01. That builds the variables for the WHERE clause queried against your table of timestamp/float values.
Now, you can get the maximum time, grouped by just the common date portion of the timestamp, but retaining the full actual date AND time of the entry where the HOUR() of the entry is before 10am...
From that, re-join back to the original table where the FINAL "LastPerDay" time matches the per-day basis. Now, you MAY get multiple entries if the actual last timestamp entry for the same day actually HAS multiple exact time entries to the granularity of hh:mm:ss (or whatever precision)
select
PreQuery.JustTheDate,
YT2.FloatColumnName
from
( select
Date_Format( YT.TimeStampColumn, '%Y-%m-%d' ) JustTheDate,
max( YT.TimeStampColumn ) as LastPerDay
from
( select #FirstOfThisMonth := Date_Format( '%Y-%m-01' ),
#FirstOfPriorMonth := Date_Sub( #FirstOfThisMonth, interval 1 month ) ) sqlvars,
YourTable YT
where
YT.TimeStampColumn >= #FirstOfPriorMonth
AND YT.TimeStampColumn < #FirstOfThisMonth
AND Hour( YT.TimeStampColumn ) < 10
group by
`JustTheDate`
order by
`JustTheDate` DESC ) PreQuery
JOIN YourTable YT2
ON PreQuery.LastPerDay = YT2.TimeStampColumn
My app stores payments done by clients. At the end of every month, the total paid that month is calculated and given to owner: I have a payments table that has the following fields (the most important).
id, datepaid, endingdate (actual month's closing date), ammount, type, code, ...
Now, having a year of payments, I've been asked to create a graph of payments evolution (totals) of latest 12 months.
By reading, etc. this is the query I've got, but I don't know how to get the latest 12 months totals (and to get 0 in case no payment was done that month)....
SELECT id, endingdate, datepaid, SUM(ammount) AS total
FROM `sis_payments`
WHERE endingdate >= DATE_SUB( CURDATE( ) , INTERVAL 1 YEAR )
GROUP BY endingdate
I know it may be badly designed, but it's what I was given... any clues? Thanks
You could try GROUP BY YEAR(endingdate), MONTH(endingdate), or something equivalent using DATE_FORMAT. Take a look at the Mysql documentation for DATE_FORMAT.
Also, don't include the date fields (endingdate, datepaid) in the SELECT clause. Instead, use YEAR(endingdate), MONTH(endingdate), just like in GROUP BY.
Getting 0 when there were no payments that month is a little more complicated in SQL. You could handle that in PHP, after running the query.
UPDATE
Example using DATE_FORMAT:
SELECT
DATE_FORMAT(mrendido,'%y-%m') as xyearmonth,
SUM(FORMAT(ammountpaid,2)) AS ammtotal
FROM sis_pyments
WHERE mrendido >= DATE_SUB(CURDATE(), INTERVAL 1 YEAR)
GROUP BY xyearmonth
ORDER BY xyearmonth ASC
I have a table with a date stamp E.g (1241037505). There's also a column with the number of views.
The data stamp resembles when it was created.
So I want to select the top viewed threads from the past week.
How do I do this?
Try this:
SELECT * WHERE
DATEDIFF(NOW(),created_date) < 7
SELECT * FROM table WHERE createdon > SUBDATE(NOW(), '7 day') ORDER BY hits DESC;
See: http://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html#function_subdate
The data you're currently tracking isn't going to allow you to select the top viewed in the last week. It will show you the top viewed over all time, or the most viewed items created in the last week. If something was created two weeks ago, but was viewed more than anything else during the last week you cannot determine that from the data you're tracking. One way I can see to do it would be to track the number of hits each content item gets each day of the week.
create table daily_hits {
cid integer, -- content id points to the table you already have
dotw smallint, -- 0-6 or similar
hits integer
PRIMARY KEY (cid, dotw)
}
Whenever you increase the hit count on the content item, you would also update the daily_hits table for the given content id and day of the week. You would need a function that converted the current date/time to a day of the week. MySql provides DAYOFWEEK for this purpose.
To get the most viewed in the last week, you could query like this:
SELECT cid, SUM(hits) FROM daily_hits GROUP BY cid ORDER BY SUM(hits) DESC
You will need some type of scheduled job that deletes the current day of the week at midnight so you aren't accumulating forever and essentially performing the same accumulation happening on the hits column of the current table.
SELECT * FROM table WHERE Date_Created > (7 days ago value) ORDER BY Hits LIMIT 0,100
or you could use this (per WishCow's Answer)
SELECT * FROM table WHERE Date_Created > SUBDATE(NOW(), '7 day') ORDER BY Hits LIMIT 0,100