MySQL: could not select data with time range - mysql

I wanted to select data, if date is matched and time is in between start time and end time. I have tried in many ways, but i am not succeed.
check 3rd row in data table in below, start time 08:00:00 and end time is 11:00:00. it means 09:00:00 is between 08:00:00 and 11:00:00
Here is my Query:
SELECT * FROM (`rides`) WHERE `date` = '2013/04/30' AND `start_time` >= '9:00:00' AND `end_time` <= '9:00:00'
Table structure if you need to know the datatype of field:
CREATE TABLE IF NOT EXISTS `rides` (
`id` int(11) NOT NULL AUTO_INCREMENT,
...,
...,
`date` date NOT NULL,
`start_time` time NOT NULL,
`end_time` time NOT NULL
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=19 ;
Data in table:

You wrote :
check 3rd row (...) it means 09:00:00 is between 08:00:00 and 11:00:00
I am assuming you expect this row in your result set. Obviously, your WHERE condition is wrong. What you want is:
WHERE ... start_time <= '9:00:00' AND '9:00:00' <= end_time
or alternatively
WHERE ... '09:00:00' BETWEEN start_time AND end_time
Notice the leading 0 is required in the above example. A more canonical form would be:
WHERE ... CAST('9:00:00' AS TIME) BETWEEN start_time AND end_time

You can use between clause of MySQL
Have a look here
http://www.tutorialspoint.com/mysql/mysql-between-clause.htm

From looking at your data, the query should not return any data because there are no suitable rows of data in your table.

Related

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 count all rows in table which are before the current month and current year

I have rows in xyz table in which each record having a column dated and one column that is is_decided which holds 1 or 0.
My Problem is that i want to get all the rows which has is_decided = 1 and the dated column must have one month before from the current month.
for this i used the following query:
SELECT COUNT(sno) AS total
FROM xyz
WHERE
dated > DATE_SUB('2016-02-01',INTERVAL 1 MONTH) AND
is_decided = 1
here in the query the hard coded date is the current date from mysql database. (NOW()).
Any help will be appreciated.
EDIT
I need all record according to the query which should qualify the condition and all the record must be surely before from the current month.
EDIT
SHOW CREATE TABLE xyz
--------------------------------
CREATE TABLE `xyz` (
`sno` INT(11) NOT NULL AUTO_INCREMENT,
`dated` DATE NOT NULL COMMENT 'fixed date to this fir for hearing',
`is_current` TINYINT(1) NOT NULL DEFAULT '0' COMMENT 'current record',
`is_decided` TINYINT(1) NOT NULL DEFAULT '0' COMMENT '0=not decided 1=decided',
`date_entry` DATE NOT NULL COMMENT 'entry of this record',
PRIMARY KEY (`sno`)
) ENGINE=INNODB AUTO_INCREMENT=45 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
You could use DATEADD().
SELECT COUNT(sno) AS total
FROM xyz
WHERE DATE_ADD(dated,1 MONTH) < NOW()
AND is_decided = 1

MySQL: Finding the first and last dates of a year from a given `Date` object

I have a table caled "Ongoing_Portfolio" Below is its structure.
CREATE TABLE `ongoing_portfolio` (
`idOngoing_Portfolio` int(11) NOT NULL AUTO_INCREMENT,
`Updated_Date` date NOT NULL,
`Investment_Value` double NOT NULL,
`Cash_Value` double NOT NULL,
`idPortfolio` int(11) NOT NULL,
PRIMARY KEY (`idOngoing_Portfolio`),
KEY `fk_Ongoing_Portfolio_Portfolio1_idx` (`idPortfolio`),
CONSTRAINT `fk_Ongoing_Portfolio_Portfolio1` FOREIGN KEY (`idPortfolio`) REFERENCES `portfolio` (`idPortfolio`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8
I need to get the first day and last day of Updated_Date year. Below is my attempt.
//Get the first date
SELECT EXTRACT (YEAR FROM `Updated_Date`)
FROM Ongoing_Portfolio WHERE `idPortfolio` = 1
//Get the last date
SELECT EXTRACT (YEAR FROM `Updated_Date`)
FROM Ongoing_Portfolio WHERE `idPortfolio` = 1
I know my attempt is not completed, but that is also incorrect. I am getting errors!
What I expected is, if the Updated_Date is 2014-05-06 the first query should return 2014-01-01 and the second query should return 2014-12-31
How can I do this in MySQL please?
You can use only one query for getting first and last day
SELECT MAKEDATE(YEAR(`Updated_Date`),1) as first_date ,MAKEDATE(YEAR(`Updated_Date`),365) as last_date FROM Ongoing_Portfolio WHERE `idPortfolio` = 1
You can easily access first_date and last_date from db results

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

MySQL Select next 2 rows greater than time

I have a database that has stored time values for a train schedule. This is my table:
CREATE TABLE IF NOT EXISTS `bahn_hausen` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`time` time NOT NULL,
`day` varchar(12) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=132 ;
Now I want to select the next two rows after now():
SELECT time FROM bahn_hausen WHERE time > now() LIMIT 2
The Problem is that when now is > than last time today (23:45:00), there is no row selected. However, I want to select the next 2 values of course (00:15:00 and 00:45:00). This only works correctly when now() is >= 0:00:00
*[edit]*For clarification: The problem I am having is that SQL doesn't recognize 00:15 to be greater than 23:45.
How do I do this?
Thanks for any help.
Your query is almost there. You just need an order by:
SELECT time
FROM bahn_hausen
ORDER BY time > now() desc, time
LIMIT 2;
Have you try to use the method CURTIME() or DATEDIFF(...) > 0
https://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html#function_current-time