Counting timestamps with Laravel 4 Query Builder - php

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

Related

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.

PHP count mysql row with changed date format

I have next problem:
My table date format was: LIKE 2017-01-08 18:50:25 (with time).
When i use sql query like
'SELECT date FROM table WHERE date = "2017-01-08"'
My row was empty, i need COUNT all row with same (today) date WITHOUT TIME.
Note, i will not change INSERT date time!
Use DATE() to get the date portion of the datetime field and compare it to today. Use COUNT() to get the number of records that match your query.
SELECT count(*) FROM table WHERE DATE(date) = CURDATE()
You can also replace CURDATE() with NOW(), CURRENT_DATE(), and CURRENT_DATE
You can also use it in the following way
'SELECT date FROM table WHERE date_format(date,'%Y-%m-%d') = "2017-01-08"'
the date_format is mysql function which return date according to your pattern the above pattern only return the Y-m-d from the datetime
I hope it will help you
plz change your statement equal operator to greater than
'SELECT date FROM table WHERE date > "2017-01-08"'
as by default if time portion is not present then it is putting 00:00...

Counting distinct days from DateTime in MySQL

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

Time date comparsion in PHP

I have a table in my database that stores user input as a start date and end date after that, my users will have to select a time range and I have to display those records in the table that are within this time range?
Tried stritotime(); and many other unctions but somehow I can't get the right results..
Any possible solution would be appreciated.
Thank you!
May be with:
SELECT count(*) FROM `table`
where
created_at>='2011-03-17 06:42:10' and created_at<='2011-03-17 06:42:50';
or use between:
SELECT count(*) FROM `table`
where
created_at between '2011-03-17 06:42:10' and '2011-03-17 06:42:50';
it depends on your record what u want to display because i didnt see your table and an exemple what you you really to do so just change count(*) and get whatrecords you want.
EDIT:
if the users will select a range of time then they will be variables
then it will be something like that
SELECT records FROM `table`
where
created_at >= '".$var_start_time."' and ended_at <= '".$var_end_time."';
you can use in mysql query BETWEEN ... AND ... comparasion operator
http://dev.mysql.com/doc/refman/5.0/en/comparison-operators.html#operator_between
You can simply do this in your SQL, which is the recommended approach. If you have these start and end times stored in your database table as native DateTime types, for example, you can use your DBMS' Date functions to select the range as a UNIX timestamp (if that's what what you want).
SELECT UNIX_TIMESTAMP(`start_time`), UNIX_TIMESTAMP(`end_time`) FROM `table` WHERE `start_time` > INTERVAL -1 DAY AND `end_time` < NOW();
That's one example (assuming you're using MySQL) where you select all rows in the table where the column start_time is within the past 24 hours and the end_time column is up to the current server time.
To get the formatted date and then do the conversion to a UNIX time-stamp in PHP use:
SELECT `start_time`, `end_time` FROM `table` WHERE `start_time` > INTERVAL -1 DAY AND `end_time` < NOW();
and then in PHP you can do:
$result['start_time'] = strtotime($result['start_time']);
$result['end_time'] = strtotime($result['end_time']);
Keep in mind that strtotime expects the formatted date to comply with PHP's date parsing rules found here.
P.S: The function in PHP you're looking for is strtotime not stritotime.

Fetching each records in MySQL table within specific date range

can anyone suggest me way to display all records in MySQL table within a specific date range, and if no records available on the date, it will still display as NULL?
SELECT * FROM table_name WHERE date IS NULL OR date BETWEEN 'date1' AND 'date2';
If you wish to include date2 with the result, use this
SELECT * FROM table_name WHERE date IS NULL OR date BETWEEN 'date1' AND ADDDATE('date2', INTERVAL 1 DAY);

Categories