Counting distinct days from DateTime in MySQL - php

I have DB table that logs request with an IP column and a DateTime stamp. I'm trying to fetch this data in a way that makes me count the number of days a certain IP has made requests. I'm using Laravel's query builder.
So far, this is what i've got:
$data = DB::table('requests')
->groupBy('ip')
->select('ip',
DB::raw('COUNT(DISTINCT created_at) as days'),
DB::raw('COUNT(*) as requests'))
->orderBy('days', 'desc')
->take(50)
->get();
My problem is that the timestamp also holds hours, minutes and seconds. So the "days" count will be about the same as the number of total requests. I want to only count the number of days active.

If field created_at is TIMESTAMP:
COUNT(DISTINCT FROM_UNIXTIME(created_at, '%Y-%m-%d')) as days
or if field is DATETIME:
COUNT(DISTINCT DATE(created_at)) as days

You can probably use DATE_FORMAT to do what you want.
Take a look at this question:
Selecting a distinct date by day only from datetime (YYYY-MM-DD HH:MM:SS) in MySQL

Related

How can I select data from this week using a Unix timestamp in SQL?

I have two columns in my database named dtp_s and dtp_e. Both of these columns hold strtotime() formatted ints which I then use in my PHP application to calculate hours/minutes between time intervals.
I want to display the 5 most recent records in date order, which works fine when I use this:
SELECT id
FROM _records
ORDER BY dtp_s DESC
LIMIT 5
However, I now want to convert the dtp_s back to a DateTime format in my Query and only pull out the data for that week. The issue I have is the records are for a weekly quota, my idea of pulling 5 records out covers Monday-Fri (which is all that is needed and uploaded) however, the following Monday will show the previous weeks Tuesday, Wednesday, Thursday and Friday as well.
I tried to use date_sub for a one week interval but this seems to only work on DateTime datatype columns, not a Unix timestamp:
SELECT id
FROM _records
WHERE dtp_s > DATE_SUB(NOW(), INTERVAL 1 WEEK);
ORDER BY dtp_s DESC
LIMIT 5
How only select the data that is from the current week by converting my formatted DateTime back to DateTime format? I appreciate any help in advance.
An example of my dtp_s and dtp_e is: 1595570400 1595584800
You can convert the filter value to a unix timestamp with date function unixtimestamp(), like so:
where dtp_s > unix_timestamp(now() - interval 1 week)
Actually, you can directly use unix_timestamp() with no conversion:
where dtp_s > unix_timestamp() - 7 * 24 * 60 * 60
Although unix_timestamp() can be very useful, unix_timestamp(now()) is actually redundant. You can just do the whole calculation in the domain of unix timestamps.

MySQL filter for specific dates when dates just saved as UNIX timestamp

I am using PHP to access a MySQL database. I have a table built up like this:
Table headers:
id (INT, auto increment), profileid, timestamp
Table content:
1, 12345678, 1513814399 (= 12/21/2017)
2, 13451983, 1513814400 (= 12/21/2017)
3, 12345678, 1513944000 (= 12/22/2017)
4, 12345678, 1513944001 (= 12/22/2017)
The table shows which profileids have been called by a website visitor at which time.
So my question is now, how is it possible to show for example:
"Give me the number of entries for profile no. 12345678 called on 12/22/2017", which would be "2" in this case.
I tried it with this query:
SELECT COUNT(profileid), from_unixtime(timestamp, '%d') AS day, from_unixtime(timestamp, '%m') as month, from_unixtime(timestamp, '%Y') as year WHERE profileid='12345678' AND day=22 AND month=12 AND year=2017;
But it is not possible to access the columns "day", "month" and "year" because they to not exist in the table.
Can someone give me a tip how to do this? Another way would be to create three new columns (timestamp_day, timestamp_month and timestamp_year), but that's not a nice solution.
Thank you in advance!
teha
Just produce the date. I think you want:
SELECT COUNT(profileid)
FROM t
WHERE DATE(from_unixtime(timestamp)) = '2017-12-22' AND
profileid = '12345678';
I would be more inclined to write this as:
SELECT COUNT(profileid)
FROM t
WHERE profileid = '12345678' AND
timestamp >= UNIX_TIMESTAMP('2017-12-22') AND
timestamp < UNIX_TIMETAMP('2017-12-23');
This allows the query to make full use of an index on t(profileid, timestamp).
You can use MySQLs DAY, MONTH, and YEAR functions combined with FROM_UNIXTIME.
SELECT COUNT(profileid)
WHERE profileid='12345678'
AND DAY(FROM_UNIXTIME(timestamp))=22
AND MONTH(FROM_UNIXTIME(timestamp))=12
AND YEAR(FROM_UNIXTIME(timestamp))=2017;
A few things here.
You can convert your raw timestamp to a MySQL TIMESTAMP object with FROM_UNIXTIME(timestamp). You already know that.
Once you have a TIMESTAMP you can use all sorts of date functions on it.
You can convert the other direction with UNIX_TIMESTAMP()
When you're looking up records for one day you can do date range searching.
So your query should maybe be
SELECT COUNT(*) cnt
FROM t
WHERE profileid = '12345678'
AND timestamp >= UNIX_TIMESTAMP('2017-12-22')
AND timestamp < UNIX_TIMESTAMP('2017-12-23')
That will pick up every timestamp value on the day you want, up to but not including midnight on the next day. If you have an index on (profileid, timestamp) this kind of query will be fast.
Note you can also do
SELECT COUNT(*) cnt, profileid
FROM t
WHERE timestamp >= UNIX_TIMESTAMP('2017-12-22')
AND timestamp < UNIX_TIMESTAMP('2017-12-23')
GROUP BY profileid
and get a result set showing the counts for all profile ids for that day. And, you can do
SELECT COUNT(*) cnt, profileid, DATE(FROM_UNIXTIME(timestamp)) day
FROM t
WHERE timestamp >= UNIX_TIMESTAMP('2017-11-01')
AND timestamp < UNIX_TIMESTAMP('2017-12-01')
GROUP BY profileid, DATE(FROM_UNIXTIME(timestamp))
and get everything for November.
You can do this
SELECT COUNT(*) cnt, profileid, LAST_DAY(FROM_UNIXTIME(timestamp)) month_ending
FROM t
WHERE timestamp >= UNIX_TIMESTAMP('2017-01-01')
AND timestamp < UNIX_TIMESTAMP('2018-01-01')
GROUP BY profileid, LAST_DAY(FROM_UNIXTIME(timestamp))
and get a month-by-month summary for a whole year.
Date arithmetic is useful. That's why many table designs use actual datestamp-like fields, like DATETIME and TIMESTAMP, rather than raw integer timestamps.

MySQL query where date range is exactly 1 month

I am trying to abstract querying a month of data on the MySQL level without having to implement a series of conditions that determine the last day of a given month on a given year. LAST_DAY() seemed to be the answer but it appears to only return the date and not the provided time.
SELECT LAST_DAY('2011-02-05 23:59:59');
returns
2011-02-28
When I try to use it in a query, I lose all the entries from the last day of the month because without time the date value is not accepted.
SELECT * FROM subscriptions
WHERE (`modified_at` BETWEEN '2014-12-01 00:00:01' AND LAST_DAY('2014-12-01 23:59:59'));
How can I modify this query so that the LAST_DAY function either generates the last time of the day or preserves the time given?
How about changing the logic to ignore times?
SELECT *
FROM subscriptions
WHERE `modified_at` >= '2014-12-01' AND
`modified_at` < date_add('2014-12-01', interval 1 month)
And this doesn't need last_day().
Use ADDTIME(expr1,expr2);
Like this:
ADDTIME(LAST_DAY('2011-02-05 23:59:59'), '23:59:59')

Counting timestamps with Laravel 4 Query Builder

I have a table logging requests to my site with an ip and a timestamp in DateTime format.
I run a query to check the ip's with most requests like this.
$ips = DB::table('requests')
->groupBy('ip')
->select('ip', DB::raw('COUNT(DISTINCT created_at) as days'), DB::raw('COUNT(*) as requests'))
->orderBy('requests', 'desc')
->take(50)
->get();
The "days" attribute is supposed to count the number of days an ip address has been active. My problem is that my timestamps are Y-m-d H:i:s, which means, by counting the DISTINCT timestamps, i get basically the same count as with requests. Hence i need a way to only count the timestamps by day, month and year.
Any help is very much appreciated.
Try using date_format inside COUNT(DISTINCT)
CREATE TABLE mytable (
id INT PRIMARY KEY AUTO_INCREMENT,
created_at DATETIME
)
INSERT INTO mytable (created_at) VALUES ('2013-01-01 12:00:01');
INSERT INTO mytable (created_at) VALUES ('2013-01-01 20:00:01');
INSERT INTO mytable (created_at) VALUES ('2013-02-01 20:00:01');
SELECT COUNT(DISTINCT DATE_FORMAT(created_at, '%Y-%m-%d')) FROM mytable

Date Comparision in PHP and my sql

i want to compare database field of date that has YYYY-MM-DD
format and i want to compare from MM-DD
actually i want to fetch records those have birthdays between month /selected week durations
and birthdate is stores as YYYY-MM-DD format in db table
how can i achieve this kindly help.
Look at this:
http://dev.mysql.com/doc/refman/5.6/en/date-and-time-functions.html
you can use CURDATE(), DATE_ADD() and DATE_SUB() to make date interval
Within your sql you could try something like the following:
select * from people where birthdate>='10/01/2010' AND birthdate<='30/01/2010';
if you want to get more specific with months and days then you can utilise the month(birthdate) and day(birthdate) functions in mysql;
select * from people where month(birthdate)=10;
would return all your people where the month for birthdate is October.

Categories