Issue of PHP and MySql function - php

while fetching data from MySQL for today's date, what should be preferred why
1) "select * from table1 where created_dt Like CURDATE()";
2) "select * from table1 where created_dt Like ".date(Y-m-d H:i:s);
will it make any difference in execution time of the script, If i use MySql function instead of php function or vice versa

will it make any difference in execution time of the script
Definitely NO.

The difference would be pretty negligable, though generating the date in SQL would probably be marginally faster.
You should not be using 'like' though, since that is for partial string comparisons, and you are using a date field (which, internally, will be an integer). You are also missing two sets of quotes for your php date example.
But most importantly, if you are using a datetime format for created_dt, and then attempting to match by date using date(created_dt) or any kind of string comparison, you will not be taking advantage of indexing, and are likely to cause a full table scan. You'd be better using:
select * from table1 where created_dt between CURDATE() and date_add(CURDATE(), interval 1 day);
Which can take advantage of a btree index on created_dt to make your query perform considerably faster and more efficiently.

It would be best to use option 1 - date value computed on the database server because:
MySQL doesn't need to convert the string value from the query to a date, since CURDATE retrieves a DATE value
the PHP date function parses the parameter and formates the date and concatenates the result to the query string, which is surely a more complex task then the mysql CURDATE function which has no parameters and simply retrieves the date

Related

SQL select with DATE in WHERE, what is faster?

I have a query from table of rows, where is datetime column with only year and month.
The day is always 01 and time is 00:00:00
When selecting data with php query, what is faster?
$date = "2020-04";
$query = "SELECT * FROM table WHERE datum LIKE ?",$date ;
or
$date = "2020-04";
$rok = substr($mesic,0,4);
$mesic = substr($mesic,5,2);
$query = "SELECT * FROM table WHERE YEAR(datum) = ? AND MONTH(datum) = ?",$rok,$mesic;
The table contains 100s thousands of rows
We always used to have the rule:
"Avoid functions in the WHERE Clause".
The background is that the database server has to make a table scan to calculate the function result for each row (even if it is only the key table).
So he cannot use the keys efficiently!
LIKE is faster!
If you use the beginning of the key (as you write), it can also use it efficiently.
I would recommend:
$date = "2020-04";
$sql = "SELECT * FROM table WHERE datum = concat(?, '-01')", $date;
The base idea is not not apply functions (either date functions or pattern matching) on the column being searched, as this prevents the database from taking full advantage of an index on that column (and it involves unnecessary additional computation for each and every row). Instead, you can easily generate the exact value to search for with by concatenating the variable in the query.
In the more typical case where datum had real day and time components, and you want to filter on a given month, you would do:
SELECT *
FROM table
WHERE datum >= concat(?, '-01') AND datum < concat(?, '-01') + interval 1 month
Note that this assumes that you are using MySQL, because the syntax suggests it. Other database have equivalent ways to build dates from strings.
Neither. In both cases you have a function call on the datum column. With YEAR() and MONTH() it is obvious. With LIKE you are converting to a string. Both impede the optimize and prevent the use of indexes.
The correct structure would be:
where datum >= ? and
datum < ? + interval 1 month -- syntax might vary depending on the database
where ? are parameter place-holders for the beginning of the month. I would suggest that you construct this in the application as a date constant or a string constant of the canonical form YYYY-MM-DD.

Get all rows from a specific month and year

I have a PHP scirpt that is always querying all the data from a database table and it's getting pretty slow. I really just need the data of a specific month and year.
Is there a simple way to get only those entries? For example, everything from February 2013?
The column that stores the dates in my table is of type datetime, if that applies to the solution.
You can add that condition in the WHERE clause of your select statement. I would recommend using BETWEEN operand for two dates:
SELECT myColumns
FROM myTable
WHERE dateColumn BETWEEN '2013-02-01' AND '2013-02-28';
If you mean to say you want everything beginning with February 2013, you can do so using the greater than or equal to operator:
SELECT myColumns
FROM myTable
WHERE dateColumn >= '2013-02-01';
EDIT
While the above are my preferred methods, I would like to add for completeness that MySQL also offers functions for grabbing specific parts of a date. If you wanted to create a paramaterized query where you could pass in the month and year as integers (instead of a start and end date) you could adjust your query like this:
SELECT myColumns
FROM myTable
WHERE MONTH(dateColumn) = 2 AND YEAR(dateColumn) = 2013;
Here is a whole bunch of helpful date and time functions.
You should index the datetime field for added efficiency and then use Between syntax in your sql. This will allow the mysql engine to remove all records that you are not interested in from the returned data set.

Mysql timezone and selecting rows from one day

I use MySQL DATETIME column to store date & time. Dates are in UTC. I want to select item from one day. What i'm doing now:
SELECT * FROM data WHERE DATE(CONVERT_TZ(datetime, 'UTC', 'Australia/Sydney')) = '2012-06-01'
note that the timezone depends on user
Problem is that it is quite slow with table growing.
Is there any solution how to make it faster?
Currently your query has to compute the conversion for every row of the database. You probably could make things better by converting the other way round, so that the conversion only occurs once (or actually twice, as you'll have to form a range). Then a proper index on datetime should make things pretty fast.
SELECT * FROM data
WHERE datetime BETWEEN CONVERT_TZ('2012-06-01 00:00:00', 'Australia/Sydney', 'UTC')
AND CONVERT_TZ('2012-06-01 23:59:59', 'Australia/Sydney', 'UTC')
Or if you worry about a 23:60:00 leap second not getting matched by any query, you can do
SELECT * FROM data
WHERE datetime >= CONVERT_TZ('2012-06-01', 'Australia/Sydney', 'UTC')
AND datetime < CONVERT_TZ('2012-06-01' + INTERVAL 1 DAY, 'Australia/Sydney', 'UTC')
In the latter form, you wouldn't have to add the hours PHP-side but instead could simply pass the date as a string parameter.
Depending on your real goal, using TIMESTAMP instead of DATETIME may be a good solution.
TIMESTAMP stores the datetime as UTC, converting as it stores and as it is fetched, from/to the local timezone. This way, what I read from your table is automatically different than what you stored (assuming we are in different timezones).
Yes, use #MvG's approach of flipping the query. Yes, use his second form.
And index the column. In composite indexes, put the timestamp last, even though it is more selective.
DO NOT do SELECT *
Indexing - make sure apropriate colunms/id
fields are indexed.
Do time-conversion php-side.
OR make sure you do 1 & 2 and it may be wrapped into a Stored Proc, passing timezone as param.
Currently MySQL query will be as below:
SELECT * FROM data
WHERE datetime >= CONVERT_TZ('2012-06-01', '+00:00', '+10:00')
AND datetime < CONVERT_TZ('2012-06-01' + INTERVAL 1 DAY, '+10:00', '+00:00')

Letting MySQL figure out date intervals vs. PHP

In a MySQL 5.1 InnoDB environment, what is the best way to SELECT data based on date intervals?
Letting MySQL do it via something like DATE_SUB(CURDATE(), INTERVAL 5 DAY) > created_at
Or have PHP prepare the date before submission via strtotime?
I would do it via the query to MySql. That way, you keep the logic of selecting dates out of the PHP. The PHP just handles the display, and you get the advantage of smaller chunks of data coming out of the database as well.
I don't think it matters from performance point of view in this case. Your expression (DATE_SUB) will be evaluated just once. Another point is that your webserver and mysql server can use different timezones, so you may have different results.
I would keep as much logic closest to the database - it has more ability to do any optimisations. Also gives the ability to do change tables easier, change the use of PHP (perhaps java/C# ...) in the future. It also differentiates beteen database (for the data), PHP (for HTML delivery), Javascript (for user enjoyment), CSS (to make things pretty)
You can select a date range using BETWEEN ... AND ...
SELECT * FROM table1 t1 WHERE now() BETWEEN t1.startdate AND t1.enddate
or
SELECT * FROM table1 t1
WHERE t1.somedate BETWEEN DATE_SUB(now(),INTERVAL 1 DAY) AND now()
I prefer this syntax because it's so close to my mental picture of ranges.

MySQL cache and date functions

I once read in a performance blog that it is better to use PHP's date functions to set dates in a MySQL query instead of using mysql date functions like curdate() because mysql can then cache the query or the result or something like that. Does anyone have any insight into this? Does it hold any water or is it baseless?
example:
$query = 'SELECT id FROM table WHERE publish_date = \''.date('Y-m-d').'\'';
vs
$query = 'SELECT id FROM table WHERE publish_date = CURDATE()';
Any function containing CURDATE() will not be cached. Source
Hardcoding the date should still be cached as far as I can tell. Though you might want to consider using the prepare functionality instead of splicing strings into your query (for sanity and security sake).
It's quite simple actually. The MySQL server does not see your PHP code so it'll receive one of these:
SELECT id FROM table WHERE publish_date = '2010-01-18';
SELECT id FROM table WHERE publish_date = CURDATE();
It will not read your intentions either. For MySQL, '2010-01-18' is a string and is deterministic: its value is always '2010-01-18'. However, CURDATE() is not deterministic: its value varies depending on the date when you run it. Thus the first one is cacheable and the second one is not.
I personally preffer first way, because it give clear head about server time (time zone), my mysql server happend to be 10h earlier when promissed :)
localtime in your PHP script will apply in SQL

Categories