Yes I've read the docs here
I have the following query:
SELECT * FROM db.table
WHERE event_type = 3
AND (YEAR(event_time) = 2014 AND MONTH(event_time) = 10)
This returns all records from October 2014. Great. Only wanted to ask, is there a shorter, better or neater way than having to write (YEAR(event_time) = 2014 AND MONTH(event_time) = 10)? Is this the "conventional" way of extracting a particular month in a given year?
Learning here.
If you have an index on the event_time column, using YEAR and MONTH (or pretty much any function) will prevent the index being used to optimize the query fully. Something like this will be fastest; I'll leave it to you to determine if it's neatest:
SELECT * FROM db.table
WHERE event_type = 3
AND event_time >= '2014-10-01' AND event_time < '2014-11-01'
That will give you everything in October 2014, and it's fully optimizable.
You can create a temporary view using the with clause of the records in the year 2014 and then extract only October from that view.
Because everytime the query needs to check if it is 2014 and month October.
So I think views will do it better.
Also you can enhance the performance by adding index
Related
I want to get the date of birth of a cat as a range of years.
The year range is as follows, and several selections are possible.
Year : [2000, 2010, 2020]
If I select 2020, the period from 2020-01-01 to 2029-12-31.
If I select 2000, 2020, the period from 2000-01-01 to 2009-12-31 and 2020-01-01 to 2029-12-31.
<TABLE>
CAT {
ID number,
Birth DateTime,
...
}
I have searched for various ways through books and Google, but I can't find the way I want to do so..
select * from CAT
where birth between '2000-01-01' and '2009-12-31'
or birth between '2010-01-01' and '2019-12-31'
or birth between '2020-01-01' and '2029-12-31'
I tried to use 'Between' or '-01-01', but if [2000, 2020] is selected, it must be connected with 'or'.
The more or, the slower the speed.
Please tell me a good way to do range calculations being able to use index.
The index is being used for BirthDate.
Add) In my db, the query of 'SUBSTRING(YEAR(CAT.birth),1,3) IN (200,202)' works quickly.
I have 500,000 data, can I use it like this?
All you need to do is add index to column birth and run your query above with BETWEEN and OR.
if you are using mysql, did you tried with YEAR() function ?
Example:
SELECT * FROM cat WHERE YEAR(birth) BETWEEN 1990 AND 2018 ORDER BY YEAR(birth) ASC;
Please check this Mysql YEAR()
If you expect to get more than about 20% of the rows from a table, then an INDEX will be eschewed for simply scanning all the rows.
Otherwise, having INDEX(birth) will help with certain queries, but none of the ones mentioned so far. Each of them is not "sargable" .
To use the index (and be efficient for a limited range of years or date range), something like this is probably what you need. This example covers 2 calendar years.
WHERE CAT.birth >= '2018-01-01'
AND CAT.birth < '2020-01-01'
BTW: SUBSTRING(YEAR(CAT.birth),1,3) can be simplified to LEFT(CAT.birth, 3), but that still cannot use the recommended index.
BTW: A 'bug' in your code: Since birth is a DATETIME, and '2009-12-31' excludes but midnight of the morning of New Year's Eve. Note how I avoided this common 'bug' by using < and the next day. This works whether you have DATE, DATETIME or DATETIME(6), etc.
I have a table that I'd like to run a SQL query on. I want to find all the customers that have a status active and have their interval_type set to interval. That part is fine, it's the next part I'm struggling with.
I want to find any orders that are to be processed between between Dec 1st 2019 and Dec 6th 2019.
The difficulty is that in my table I have the columns "interval", this can be a number between 15-75 days (and is converted to seconds) and when their order was last processed (also a unix timestamp) in the column called "last_processed".
If the "interval" (in seconds) is added to the "last_processed" (a date), does that new date fall between the 1st and 6th of Dec. How can I do that?
SELECT *
FROM subscriptions
WHERE
status = 'active' AND
interval_type = 'interval' AND
`interval` BETWEEN 1575158400 AND 1575676740;
Here's what the data looks like in my table:
You can do it this way
SELECT *,
FROM_UNIXTIME(last_processed+`interval`)
FROM subscriptions
WHERE status = 'active' AND
interval_type = 'interval'
AND (last_processed + `interval`) BETWEEN UNIX_TIMESTAMP('2019-12-01 00:00:00')
AND UNIX_TIMESTAMP('2019-12-06 23:59:59');
DBfiddle Example
Next time please use text instead or directly a dbfiddle example, than you can get an answer much earlier. That's why i posted the link for a minimal example.
I have created a view called acquity_fields with 4 columns (see also view from phpMyAdmin attached):
meta_id; post_id; meta_key; meta_value
I was using this post Construct MySQL query ( meta_key/meta_value table) to help me to create a query so that I can pull the last month (e.g Sept 1-30 inclusive) as well as August for number of clients.
But I need to walk first so I wanted to display all months with number of clients in each then add in the additional statements for last month and previous.
Here is the query I put together for getting all the months and clients,
SELECT COUNT(*) as Clients, MONTHNAME(FROM_UNIXTIME(meta_key = 'wpcf-acquity-date')) as Month
FROM acquity_fields
WHERE (meta_key = 'wpcf-acquity-date')
GROUP BY Month
but it seems to be putting all the clients into one month and displaying it as:
Clients | Month
----------------------
399 | January
I am not sure if its the time conversion, but I am stumped to what is causing this. Any help would be great and thanks in advance!
View acquity_fields in phpmyadmin
In your select part of the query, FROM_UNIXTIME() takes in a timestamp, so try this:
SELECT COUNT(*) as Clients, MONTHNAME(FROM_UNIXTIME(meta_value)) as Month
FROM acquity_fields
WHERE (meta_key = 'wpcf-acquity-date')
GROUP BY Month
(meta_key = 'wpcf-acquity-date') is a WHERE condition, not a timestamp integer. If you have something that's not a timestamp, the system will treat it as a default date, and the output will become December or January depending on your settings.
So basically, I want to create reports for my Attendance Records Table.
Table has :user_id, :clock_in, :clock_out, :seconds columns that are being updated.
Basically my report needs: to calculate (sum of :seconds) for a given period.
I.e. Jan 1, 2014 to Jan 31, 2014 ... I would like to list all records from this daterange, and in the end would calculate sum of :seconds.
Any ideas how would I approach this?
Your question is very general, please, before question try to do some work and come with technical questions.
Tips
Your question is related about SQL, basically you need to perform a select query
select * from your_table where date <= your_date and date >= your_date
Need help on mysql date range query
In rails, where clauses are build by ActiveRecord
YourModel.where('date <= ? and date >= ?', your_date. your_date)
Rails where date is greater than given date query
If you need something more advanced, use Ransack
http://railscasts.com/episodes/370-ransack
Hope I can help you ;)
http://upic.me/i/hq/capture.png
http://upic.me/i/3g/capture.png
I have the table that divide datetime to single field and set these field to index.
i would to use where clause in date range ex. between 2010/06/21 to 2011/05/15
I try to use
where concat_ws('-',year,month,day) between '2010/06/21' and '2011/05/15'
it's work because I use concat function to adjust these field like ordinary datetime
but it not use index and query slowly.This table has 3 million record
if would to use index I try to this query
where
year = '2011'
and month between 05 and 06
and day between 21 and 15
It almost work but in last line
day between 21 and 15
I can't use this condition
I try to solve this problem but I can't find it and change structer table
I'm looking for answer
thank you
Now I can OR operation for query thank for your answer
In another case if would to find 2009/08/20 to 2011/04/15 It's use longer query and make confusion.Has someone got idea?
If it's a datestamp type, you can just use the where/between clause directly. I would consider switching to that, it's quite faster than a varchar with a custom date format.
WHERE yourdate BETWEEN "2011-05-01" AND "2011-06-15"
Although checking ranges may work for single months, you will find if you're querying between several months to have some margin of error because, if you think about it, you're selecting more than you may necessarily want. Using Datestamp will fix performance and usability issues arising from storing the date in a custom varchar.
Here are the two queries to convert your times around if you're interested:
ALTER TABLE `yourtable` ADD `newdate` DATE NOT NULL;
UPDATE `yourtable` SET `newdate` = STR_TO_DATE(`olddate`, '%Y/%m/%d');
Just change "yourtable", "newdate", and "olddate" to your table's name, the new date column name, and the old datestamp column names respectively.
If you can't change the table structure, you could use something like the following:
WHERE year = '2011'
AND ((month = '05' AND day >= 21) OR (month = '06' AND day <= '15'))
(At least, I think that query does what you want in your specific case. But for e.g. a longer span of time, you'd have to think about the query again, and I suspect queries like this could become a pain to maintain)
UPDATE for the updated requirement
The principle remains the same, only the query becomes more complex. For the range of 2009/08/20 to 2011/04/15 it might look like this:
WHERE year = '2009' AND (month = '08' AND day >= '20' OR month BETWEEN '09' AND '12')
OR year = '2010'
OR year = '2011' AND (month BETWEEN '01' AND '03' OR month = '04' AND day <= '15')
where year = 2011
and (month between 5 and 6) and (day > 20 or day < 16)
You where seperating days and month whereas you must keep them together
parentheses must be set ...
Mike
It is important that you use OR otherwise it is nonsense