how to count the number of dates in a table - php

I have a small custom blog type site and I keep track of my posts with a datetime field in the DB that hold a current_timestamp when entered.
I am working on a pagination setup and want to figure out how many unique days there are in my DB.
For example in the below screen shot there are 19 entries but only entered on 5 different days.
I want to be able to find the number of unique days in the DB. In the above shot 5.
This way I can paginate my posts by groups of days, say 7 but still show all the posts for all those days regardless of if one day has more posts or one day has none.
EX for page 1 showing the first 7 days of posts:
Jan 1st
+post
+post
+post
Jan 3
+post
Jan 4
+post
+post
Jan 5
+post
Jan 6
+post
+post
Jan 7
+post
Jan 8
+post
+post
How is the best way to get this data or paginate in this way?
Thanks

Try below:
select count(*),date from tablename group by left(date,10)
above query will give count of unique days.

This will give you the amount of posts per day:
select from_days(to_days(date)) day, count(*) from t
group by day
You can then apply a limit to the amount of records (days) to paginate them per 7 days:
select from_days(to_days(date)) day, count(*) from t
group by day
limit 7
Now, if you want to get the actual posts (I think that is what you want), you can do this:
select date, file from t t1 join (
select to_days(date) day from t
group by day
order by day desc
limit 7
) t2
on to_days(t1.date) = t2.day
This will give you all posts for the 7 most current days. Is that what you where looking for?
Edit:
I may be misinterpreting or did not ask my question well but I want the the count of all total unique days not posts. - ian
LOL: That's easier :)
select count(distinct to_days(date)) from t

I guess what you are looking for is
SELECT count(*) from table group by DATE(date)
the trick is to map datetime into date via DATE() function
UPDATE: sorry I missinterpreted your question. This will return the number of posts in each day.
To get number list of unique days you could do
SELECT DISTINCT DATE(datetime) from table
To get number of unique days you could either check the count of it in your back-end language or make a subquery, like:
select count(*) from (select distinct date(datetime) from table) as res

Related

CakePHP - SQL Query to join 3 tables

i have 3 tables
News(id, year_id, month_id, title, description) where year_id and month_id are foreign keys from tables
years(id,...) and
months(id,...)
respectively.
2014 - 2015 - 2016 - 2017
January
news title 1 (January 1, 2014)
news title 2 (January 17, 2014)
February
news title 1 (February 5, 2014)
news title 2 (February 20, 2014)
As you can get an idea that first of all, i want to show all year's list(2013, 2014, 2015) and i did it successfully.
And now i want that below that list of years, the news must be displayed grouped according to months(e.g. all news of January month under "January" heading and so on till December of Year 2014 and below that, similarly complete set of all news according to months of Year 2015 and so on....)
I just want to know if there is any way to get required results from a SQL join or group by query
or i will have to manage this 100% using coding and by simply fetching all records from table without any query.
I have searched for this on google but not getting the solutions.
Need just a little idea regarding this.....
I may know nothing about CakePHP and I've been wondering why would you ever have separate tables with month and year ID's.. as I've asked in a comment which you didn't mind replying.
Anyway, if you want to keep your database structure, just use this :
SELECT
news.title,
months.name,
months.day,
years.year
FROM news
JOIN months ON months.id = news.month_id
JOIN years ON years.id = news.year_id
ORDER BY
months.month ASC,
years.year ASC
I think this should do ( did not check obviously if there's any error but.. this is the idea ).
You cannot group since we're not using any aggregate function.
To note that I just assumed the columns of years and months as I have no idea how did you name your other columns from those tables aside the id which I guess it's just an index but you can replace them as you wish
Even though I suggest getting rid of your months and years tables and just store the month and year number if you really want to in the News table as you can always output a month's name in PHP.

To make report of how many products sold where entry date is in timestamp

I have a product table with product_id and entry_date field (which is varchar and have timestamp value by time() function in php). I want to get result of how many products have been uploaded per week. Please tell me the SQL so that I can get the result of how many products have been uploaded per week.
I also have user_id field.I also need how many products have been uploaded per week per user.
possible duplicate: Show most viewed entries that have been added in the last 7 days
try something like this:
SELECT data-you-want-to-retrieve
FROM `Your-Table`
WHERE entry_date > (curdate() - 604800)
So it sees that the entry date is larger than the date 7 days ago.
SELECT CONCAT(YEAR(entry_date), '_', WEEKOFYEAR(entry_date)) AS week, COUNT(*) Count, user_id
FROM `tbl_products`
GROUP BY week, product_id, user_id
Count of product uploads per week:
SELECT CONCAT(YEAR(entry_date), '_', WEEKOFYEAR(entry_date)) AS week,
COUNT(1) AS prodcnt
FROM products
GROUP BY week
Count of products per week for a particular user:
SELECT CONCAT(YEAR(entry_date), '_', WEEKOFYEAR(entry_date)) AS week,
COUNT(1) AS prodcnt
FROM products
WHERE user_id = <userid here>
GROUP BY week
You'll get results grouped by something like 2012_48, where 48 is the week of the year (goes from 1-53).

MySQL find first available weekend

I have a table which holds restaurant reservations. It just has an restaurant_id and a date column which specify the actual date (we are talking about whole day reservations).
I want to find out when is the next available weekend for a particular restaurant. A "weekend" is either Saturday or Sunday. If one of them is available, then we have an available weekend.
The query should, of course, consider the current time to calculate the next weekend.
Can anyone help?
Here's the table structure and data for the "dates" table which holds all reservations made so far:
id id_venue date
12 1 2011-04-22
13 1 2011-04-23
14 1 2011-04-24
15 1 2011-04-30
16 1 2011-05-07
17 1 2011-05-08
As you can see, the weekend of 23-24 is full, so the one of 7-8 May. What I need to find is the date of 2001-05-01 which is the first available Saturday OR Sunday after today's date.
I think the others are missing the question... They think your table may already be POPULATED with all weekends and some status as to open or not... My guess is that your table only HAS a record IF it is reserved... thus you need to find records that DO NOT EXIST AT ALL... based on some automated Look for dates...
This is a modification to another post I've done here
Although I didn't change the context of the query, I only put in the columns associated to YOUR table. I understand you are only going against a single venue table and so am I (actually). However, to understand the "JustDates" alias, this INNER PRE-QUERY is creating a dynamically populated table of ALL DATES by doing a Cartesian join against ANY other table.. in this case, your "Venue" table of reservations (I didn't see your actual table name reference explicitly, so you'll have to change that). So, this in essence creates a table of all dates starting from whatever "today" is and goes forward for 30 days (via limit), but could be 40, 50, 300 or as many as you need.. provided the "YourVenueTable" has at least as many records as days you want to test for. (same clarification in post this was derived from). This result set going out 30, 40 or however many days is pre-filtered for ONLY the given day of week of 1-Sunday or 7-Saturday... So it should return a result set of only Apr 23, Apr 24, Apr 30, May 1, May 7, May 8, May 14, May 15, May 21, May 28, etc.
So NOW you have a dynamically created result set of all possible days you are considering moving forward. Now, that gets joined to your actual Venue Reservations table and is filtered to ONLY return those DATES where it is NOT found for the id_venue you are concerned about. In your data example it WOULD find a match on Apr 23 and 24 and NOT return those records. Same with Apr 30... However, it WILL find that the record in the prequalifying list that includes May 1 will NOT find the date match in the venue table and thus include that as you are anticipating... It will then continue to skip May 7 and 8, then return May 14, 15, 21, 28, etc...
select JustDates.OpenDate
from
( select
#r:= date_add( #r, interval 1 day ) OpenDate
from
( select #r := current_date() ) vars,
Venue
LIMIT 30 ) JustDates
where
DAYOFWEEK( JustDates.OpenDate ) IN ( 1, 7 )
AND JustDates.OpenDate NOT IN
( select Venue.date
from Venue
where Venue.id_venue = IDYouAreInterestedIn
and Venue.Date = JustDates.OpenDate )
order by
JustDates.OpenDate
Note, and per the other reservations posting, the query for reservation date availability dates doing a limit of 30 above can be ANY table in the system as long as it has AT LEAST as many days out as you want to look forward for reservations... If you want all availability for an upcoming year, you would want 365 records in the table used for a Cartesian result to get the #r cycling through dynamically created "date" records.
SELECT ...... DAYOFWEEK(`date`) as `num` FROM .... WHERE num = 1 OR num = 7
I don't know how u wanna check "availability"
How about?:
SELECT * FROM table WHERE (DAYOFWEEK(date)=1 OR DAYOFWEEK(date)=7) AND restaurant_id =$RESTAURANTID AND date > CURDATE() ORDER BY date ASC LIMIT 1
Set the number of days from today until the next Saterday (if 0 then today is Saterday)
Assuming that if today is Sunday you only want reservations for the next full weekend.
select #OffsetSaterday:= mod((8-DayOfWeek(CurDate())+7,7);
You have not supplied enough info to know how the reservation database looks, so I'm going to guess here.
Every restaurant has seats:
Table seats
id: integer primary key
rest_id: integer #link to restaurant
desc: varchar(20) # description of the seat.
Table restaurant
id: integer primary key
other fields.....
Table Reservation
id: integer primary key
reservation_date: date
seat_id: integer
The select statement to get all available seats for next weekend is:
select #OffsetSaterday:= mod((8-DayOfWeek(CurDate())+7,7);
select s.*, rst.* from seats s
inner join restaurant rst on (rst.id = seats.rest_id)
left join r on (r.seat_id = s.id
and r.reservation_date between
date_add(curdate(),interval #OffsetSaterday day) and
date_add(curdate(),interval #OffsetSaterday+1 day)
where r.id is null
order by s.rest_id, s.desc;
You might be able to combine the two selects into one, but MySQL does not guarantee the order in which expressions get evaluated, so I would recommend against that.

Get Current year and next form mysql

Im am selecting various things from a table. The problem is I only want to select them if they belong to the current year and the next year.
My table looks like this
Title Text Date
The date is formated like this 0000-00-00 and is in the format "date"
So the question is how can i select only items from only this year and the next?
Example: the year is 2012, I have items in my table that is old and i dont want them to show - I only want to select items from at the first 2012 1 January and last in this case 31 Dec 2013 current year 2012 + 1 year.
Thanks a lot for any help!
SELECT
*
FROM
table
WHERE
YEAR(date) = YEAR(CURDATE())
OR
YEAR(date) = YEAR(CURDATE()) + 1
http://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html
SELECT
*
FROM
table
WHERE
date BETWEEN CONCAT(YEAR(CURDATE()),'-01-01') AND CONCAT(YEAR(CURDATE())+1,'-12-31')
As ugly as it looks, it allows your query to use index on date field.
Better idea is to create limiting dates in external PHP script, so that the query can use query cache.
If you only want to show items, that are no older than two years, you can do this:
SELECT
*
FROM
table
WHERE
date >= CURDATE() - INTERVAL 2 YEAR;

MySQL AVG(COUNT(*) - Orders By day of week query?

This query has baffled me... I've searched the web work over a day now and I have tried numerous things.
I want to get the avg number of orders for every day of the week from my db. I can pull the total # with COUNT just fine. But I just can't figure out how to get the AVG of COUNT on a GROUP BY. I've tried subqueries... functions... everything... nothing works... maybe someone can throw me a bone.
Here is the query I started with below. I know AVG(COUNT(*)) won't work but I'll leave it at that because it shows what I want to do.
SELECT
AVG(COUNT(*)) AS avgorders,
SUM(total) AS ordertotal,
DAYNAME(STR_TO_DATE(order_time,'%m/%d/%Y %H:%i')) AS day
FROM data
GROUP BY day
ORDER BY DAYOFWEEK(STR_TO_DATE(order_time,'%m/%d/%Y %H:%i')) ASC
To get the average you don't need the grand totals for each day, you need multiple daily totals for each day.
Day | Count
__________________
Monday 5
Tuesday 4
Monday 6
Tuesday 3
... ...
Then you can average those numbers. I.e (5+6)/2 for Monday.
Something like this should work:
SELECT day_of_week, AVG(order_count) average_order FROM
(
SELECT DAYNAME(order_date) day_of_week,
DAYOFWEEK(order_date) day_num,
TO_DAYS(order_date) date,
count(*) order_count
FROM data
GROUP BY date
) temp
GROUP BY day_of_week
ORDER BY day_num
UPDATE: I was originally wrong. Group the inner SELECT by the actual date to get the correct daily totals. For instance, you need to get how many orders happened Monday (2/1/10) and Monday (2/8/10) separately. Then average those totals by the day of the week.
This will do, assuming that order_time is date or datetime field ( everyone would be hapier this way ;) ). Of course there is some approximation, because oldest order can be in Friday and newest in Monday, so amount of every day of week isn't equal, but creating separate variable for every day of week will be pain in the ass. Anyway I hope it will be helpful for now.
SET #total_weeks = (
SELECT
TIMESTAMPDIFF(
WEEK,
MIN(order_time),
MAX(order_time)
)
FROM data
);
SELECT
DAYNAME(order_time) AS day_of_week,
( COUNT(*) / #total_weeks ) AS avgorders,
COUNT(*) AS total_orders
FROM
data
GROUP BY
DAYOFWEEK(order_time)
I know this is old, but i was searching for a similar solution hoping to find something someone else had used. In hopes of not doing a sub query, i came up with the below and would love any feed back!
SELECT dayofweek(`timestamp`) as 'Day',count(`OrderID`)/count(DISTINCT day(`timestamp`)) as 'Average' FROM `Data` GROUP BY dayofweek(`timestamp`)
The idea is to divide the total orders on a given day of the week, by the total number of "Mondays" or whatever day it is. What this does not account for would be any days that had zero orders would not lower the average. That may or may not be desired depending on the application.
What you are asking doesn't make sense to me... AVG is an aggregate function and so is COUNT. What's wrong with the query above but just use: COUNT(*) AS avgorders?
Lets say you had 3 rows for day1, 2 rows for day2, 5 rows for day3, and 9 rows for day4... do you want to get back a single row result that tells you:
avgorders = (3 + 2 + 2 + 5 + 9) / 5 = 21 / 5 = 4.2
ordertotal = (3 + 2 + 2 + 5 + 9) = 21
I don't think you can get that in a single query, and you'd be better off doing the second round of aggregation in a server side language like PHP operating on the results of the first aggregation.

Categories