Get value of timestamp column value in sql - mysql

I am writing a sql query to retrieve the records from date range of a month but I did not get the result. Below is my query that I tried to run.
SELECT uid FROM sessions WHERE TIMESTAMP >= '2021-10-01 00:00:00' AND TIMESTAMP < '2021-10-31 00:00:00'
timestamp column contain value in numeric
see link:
CREATE TABLE sessions (
uid int(10) unsigned NOT NULL COMMENT 'The users.uid corresponding to a session, or 0 for anonymous user.',
sid varchar(128) CHARACTER SET ascii NOT NULL COMMENT 'A session ID (hashed). The value is generated by Drupal''s session handlers.',
hostname varchar(128) CHARACTER SET ascii NOT NULL DEFAULT '' COMMENT 'The IP address that last used this session ID (sid).',
timestamp int(11) NOT NULL DEFAULT '0' COMMENT 'The Unix timestamp when this session last requested a page. Old records are purged by PHP automatically.',
session longblob COMMENT 'The serialized contents of $_SESSION, an array of name/value pairs that persists across page requests by this session ID. Drupal loads $_SESSION from here at the start of each request and saves it at the end.',
PRIMARY KEY (sid),
KEY timestamp (timestamp),
KEY uid (uid)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='Drupal''s session handlers read and write into the sessions…'

Use UNIX_TIMESTAMP to convert the datetime strings to unix timestamp numbers
SELECT uid
FROM sessions
WHERE `TIMESTAMP` >= UNIX_TIMESTAMP('2021-10-01 00:00:00')
AND `TIMESTAMP` <= UNIX_TIMESTAMP('2021-10-31 23:59:59')

First of all, you should'nt use 'TIMESTAMP' as a column name. But I think if only one example. If not, change it.
You have some options.
Using BETWEEN command
SELECT uid FROM sessions WHERE TIMESTAMP BETWEEN '2021-10-01 00:00:00' AND '2021-10-31 00:00:00'
Using MONTH and YEAR
SELECT uid FROM sessions WHERE MONTH(TIMESTAMP) = MONTH('2021-10-01 00:00:00') AND YEAR(TIMESTAMP) = YEAR('2021-10-01 00:00:00')

Related

Retrieve records using epoch date in mysql

I have a table named as data_stats. Please check below respective schema:
CREATE TABLE `data_stats` (
`uuid` varchar(255) PRIMARY KEY NOT NULL COMMENT 'Primary Key',
`state` varchar(255) NOT NULL DEFAULT 'Active',
`created_at` BIGINT(20) NOT NULL COMMENT 'Timestamp of when the record was created',
`updated_at` BIGINT(20) NOT NULL COMMENT 'Last updated timestamp');
I am storing created_at and update_at timestamp in the epoch format.
Now I need to find all the records that are updated today (i.e update_at date == today's date)
I tried below query
SELECT * FROM `data_stats` where FROM_UNIXTIME(updated_at,"%Y-%m-%d") = CURRENT_DATE
But I am getting empty results. So how can fetch records that are updated today?
Could be a mismatch in the types on the equals. To make sure, check to see if coercing both sides to DATE helps. Replace FROM_UNIXTIME(updated_at,"%Y-%m-%d") = CURRENT_DATE with:
DATE(FROM_UNIXTIME(updated_at)) = DATE(CURRENT_DATE)

MySQL subquery count with calendar table slow

I have a sales table in MySQL (InnoDB). It's +- 1 million records big. I would like to show some nice charts. Fetching the right data is not a problem. Fetching it fast is...
So I like to count the amount of sales in table A grouped per day (later on also month, and year) for PERIOD A till Z. Concrete; for the last 30 days I like to know for each day how many sales records we have in the DB.
So MySQL would have to return something like this:
I like to achieve that MySQL returns the data like this:
date, count
2017-04-01, 2482
2017-04-02, 1934
2017-04-03, 2701
...
The structure of the Sales basically like this:
CREATE TABLE `sales` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
`updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
`deleted_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `contacts_created_at_index` (`created_at`),
KEY `contacts_deleted_at_index` (`deleted_at`),
KEY `ind_created_at_deleted_at` (`created_at`,`deleted_at`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
Some days (datapoints) might not have any results, but I don't like to have gaps in the data. So I also have some 'calendar' table.
CREATE TABLE `time_dimension` (
`id` int(11) NOT NULL,
`db_date` date NOT NULL,
`year` int(11) NOT NULL,
`month` int(11) NOT NULL,
`day` int(11) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `td_ymd_idx` (`year`,`month`,`day`),
UNIQUE KEY `td_dbdate_idx` (`db_date`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
Fetching 30 rows (30 days) with a count per day takes 30 secs...
This is the first query I tried:
SELECT
`db_date` AS `date`,
(SELECT
COUNT(1)
FROM
sales
WHERE
DATE(created_at) = db_date) AS count
FROM
`time_dimension`
WHERE
`db_date` >= '2017-04-11'
AND `db_date` <= '2017-04-25'
ORDER BY `db_date` ASC
But like I said it's really slow (11.9 secs). I tried al kinds of other approaches, but without luck. For example:
SELECT time_dimension.db_date AS DATE,
COUNT(1) AS count
FROM sales RIGHT JOIN time_dimension ON (DATE(sales.created_at) =
time_dimension.db_date)
WHERE
(time_dimension.db_date BETWEEN '2017-03-11' AND '2017-04-11')
GROUP BY
DATE
A query for just 1 datapoint takes only 5.4ms:
SELECT COUNT(1) FROM sales WHERE created_at BETWEEN '2017-04-11 00:00:00' AND '2017-04-25 23:59:59'
I haven't checked innodb_buffer_poolsize on my local machine. I will check that as well. Any ideas on how to make queries like this fast? In the future I would even need to where clauses and joins, to filter the set of sales records..
Thanks.
Nick
You could try to count sale data first, then join count result with your calendar table.
SELECT time_dimension.db_date AS date,
by_date.sale_count
FROM time_dimension
LEFT JOIN (SELECT DATE(sales.created_at) sale_date,
COUNT(1) AS sale_count
FROM sales
WHERE created_at BETWEEN '2017-03-11 00:00:00' AND
'2017-04-11 23:59:59'
GROUP BY DATE(sales.created_at)) by_date
ON time_dimension.db_date = by_date.sale_date
WHERE time_dimension.db_date BETWEEN '2017-03-11' AND '2017-04-11'
The problematic part of your query is the data type conversion DATE(created_at), which effectively prevents Mysql from using the index at created_at.
Your 1 datapoint query avoids that, and that is why it is working fast.
To fix this you should check if created_at is within a range of specific day, like that:
created_at BETWEEN db_date AND DATE_ADD(db_date,INTERVAL 1 DAY)
This way Mysql will be able to make use of index on it (do a range lookup), as appropriate.
WHERE DATE(created_at) = db_date)
-->
WHERE created_at >= db_date
AND created_at < db_date + INTERVAL 1 DAY
This avoids including midnight of second day (as BETWEEN does)
Work for all flavors: DATE, DATETIME, DATETIME(6)
Does not hid the created_at inside a function where the index cannot see it.
For time_dimension, get rid of PRIMARY KEY (id) and change UNIQUE(db_date) to the PK.
After making these changes, your original subquery may be competitive with the LEFT JOIN ( SELECT ... ). (It depends on which version of MySQL.)

MySQL AVG TIME Duration Calculation and Related Functions?

table with login data of the website users with two datetime columns. One is logged in time and other one is logged out time.
table has following columns
user_id (user id of the
datetime (start login time DATETIME )
datetime_end (end logout time DATETIME)
From this data I need to generate a report or calculate the following
Daily AVG Login Duration for Users (i.e 01 March 2015 its 21 mins , 03 November 2016 its 25 mins ..etc )
second report is
Current Day (Last 24 hours) based on Hour AVG Login Duration (i.e same as above but only per hour AVG)
is there a way i can achieve this via MySQL query ? (or SQL query)
table is create is
CREATE TABLE IF NOT EXISTS `users_login` (
`login_id` int(11) unsigned NOT NULL,
`user_id` int(11) unsigned NOT NULL DEFAULT '0',
`last_ip` varchar(45) NOT NULL DEFAULT '0.0.0.0',
`server_ip` varchar(225) DEFAULT '0.0.0.0',
`country` varchar(2) NOT NULL DEFAULT '00',
`continent` tinytext,
`datetime` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`datetime_end` datetime NOT NULL DEFAULT '0000-00-00 00:00:00'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Something like this for the first one
SELECT DATE(datetime),AVG(TIMESTAMPDIFF(MINUTE,datetime,datetime_end)) as DailyAvg
FROM users_login
GROUP BY DATE(datetime)
And for hourly :
SELECT DATE(datetime),extract(hour from datetime) as HourCol,
AVG(TIMESTAMPDIFF(MINUTE,datetime,datetime_end)) as HourlyAvg
FROM users_login
WHERE DATE(datetime) = date(now())
GROUP BY DATE(datetime),extract(hour from datetime)
Of course this queries have a few exceptions.. You didn't explain you entire logic so I assumed you want to group by the hour of the login and the date of the login..

mysql insert current date, only in insert time

this is the table structure,
id int
name varchar
insert_date date
update_date TIMESTAMP
Now here the idia is , insert_date will be able to insert by defult current time & the update_date it will insert current time in each edit or insert it will update it.
so how i could make the (insert_date) default value to current time and date but on update it should not change the value of (insert_date) if i keep it TIMESTAMP on update it will change.
insert_date -- insert current time , only in insert just one time
regards
If you want to add only time .. you need to use
CURTIME()
AND if you want current date and time...
NOW()
If you want only current date....
CURDATE()
for more here..
The following SELECT statement:
SELECT NOW(),CURDATE(),CURTIME()
will result in something like this:
NOW() CURDATE() CURTIME()
2008-11-11 12:45:34 2008-11-11 12:45:34
Choose format as you want.
use DEFAULT CURRENT_TIMESTAMP for insert
use ON UPDATE CURRENT_TIMESTAMP for update
like below
CREATE TABLE IF NOT EXISTS `datetest` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(100) NOT NULL,
`timestamps_updated` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP,
`timestamps_inserted` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
)
If you want to keep default current date & time means, you want to change
insert_date data type date to datetime
And insert like
Insert into tbl(insert_date) values(now())
or
$date=date('Y-m-d H:i:s')
Insert into tbl(insert_date) values('$date')
or
Read it
How do you set a default value for a MySQL Datetime column?
Use DATETIME type if you want to store Date and time, and you can choose CURRENT_TIMESTAMP as a default value or use NOW() to get current date and time (yyyy-mm-dd Hour:minutes:seconds).
you may use NOW() function in you respective fields

Counting year and month entries from datetime fields

I have a problem constructing a mysql query:
I have this table "tSubscribers" were I store the subscribers for my newsletter mailing list.
The table looks like this (simplified):
--
-- Table structure for tSubscriber
--
CREATE TABLE tSubscriber (
fId INT UNSIGNED NOT NULL AUTO_INCREMENT,
fSubscriberGroupId INT UNSIGNED NOT NULL,
fEmail VARCHAR(255) NOT NULL DEFAULT '',
fDateConfirmed DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
fDateUnsubscribed TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY (fId),
INDEX (fSubscriberGroupId),
) ENGINE=MyISAM;
Now what I want to accomplish is to have a diagram showing the subscriptions and unsubscriptions per month per subscriber group.
So I need to extract the year and months from the fDateConfirmed, fDateUnsubscribed dates, count them and show the count sorted by month and year for a subscriber group.
I think this sql query gets quite complex and I just can't get my head around it. Is this even possible with one query.
You will need two separate queries, one for subscriptions and other for unsubscriptions.
SELECT COUNT(*), YEAR(fDateConfirmed), MONTH(fDateConfirmed) FROM tSubscriber GROUP BY YEAR(fDateConfirmed), MONTH(fDateConfirmed)
SELECT COUNT(*), YEAR(fDateUnsubscribed), MONTH(fDateUnsubscribe ) FROM tSubscriber GROUP BY YEAR(fDateUnsubscribed), MONTH(fDateUnsubscribed)