Age calculation - Fastest age calculation formula from timestamp field - mysql

I'm using this query to calc an user age:
SELECT
((YEAR(CURDATE())-YEAR(um.date_birth)) - (RIGHT(CURDATE(),5)<RIGHT(um.date_birth,5)))
FROM user_meta AS um
WHERE um.uid = 2
I wonder if there's a fastest / lighter way to do it.
I'm using this nested in a bigger select, so I wouldn't mind to somehow enhance the overall performance. Thank you.

select (CURDATE()-birth_dt)/365 from dual

If you find that you need to calculate a field too often, I would suggest you ALTER your table to add new columns to facilite your calculations.
For example, rather than calculate the YEAR for each date of birth in each query, simple add a YEAR column, update the table ONCE with the year of birth, and store the year as an INT.
That way, every time you need to catch the year, just select the field.

Related

SQL, dropping duplicates but keeping first row to mimic "greatest n per group" functionality

I'm curious about what the best approach for this might be.
Currently, I have a dummy table that stores each time a person clocked in to work. It repeats a lot of info about that employee in each row, e.g. their name, their employee id, position, etc. The main thing different, of course, is the time stamp.
If I want the latest date each employee clocked in, I'm wondering how I would do it via a drop duplicates approach. E.g. in Python, I would sort by date in descending order, and then drop_duplicates on the employee ID column. I'm wondering what the equivalent in SQL is, that isn't the greatest-n-per-group method.
As #Gordon Linoff said if you can share your data table we will be able help you better. But you can try using the MAX Keyword. Like
Select * from your_table t
Where CheckinDate = (select MAX(CheckinDate) from your_table where employeeId = t.employeeId)

fetch rows from table based on from and to dates

I have a table as shown here:
In the table there are two columns named DateFrom and DateTo.
I want to fetch row data from or between these two dates. e.g. If I want to fetch data from 2018-12-27 to 2019-01-10 it should return the two rows with HPID 1 and 6 - as both row have or comes under the mentioned dates.
Now I don't know what the SQL query should be. I have tried BETWEEN but with no result.
Actually I am working on a small hotel management system and the table shows the cost of any hotel between certain dates. So when the user searches for hotels for date between two dates it should show costs which overlap those dates.
DateFrom and DateTo Are not datetime.
Stefan Taseki's answer is almost right but doesn't deal with overlaps correctly. Swap the start and end dates round in that query and it should do the job:
SELECT *
FROM [YourTable]
WHERE DateFrom <= '2019-01-10' AND DateTo >= '2018-12-27'
P.S. You should always store your dates in datetime columns. Dates are not text. You will have issues with a) sorting, b) comparisons, and c) presenting dates in different formats if you don't do this. The datetime data type exists for good reasons, you should use it. Consider changing your database now while you can.
P.P.S. Your data is also de-normalised. Country, City, HotelName, HotelCode and HotelStar should all be in a separate "hotel" table (and country and city each should be in different tables too), and then with a foreign key on Hotel ID only in this costs table. Otherwise you keep repeating data which should only be entered once. I suggest you learn about relational database design and normalisation, if you didn't realise this.
This should work:
SELECT *
FROM [YourTable]
WHERE DateFrom >= '2018-12-27' AND DateTo<= 2019-01-10
First of all make sure that your dates are in single quotes
'SELECT * FROM your_table WHERE DateFrom BETWEEN '2018-12-27' and '2019-01-10' OR DateTo BETWEEN '2018-12-27' and '2019-01-10';
Something that is not clear is what are you trying to achieve with this query.
Casting may be required, use below query
select *from your_table_name
where date(DateFrom) >= date('2018-11-27') AND date(DateTo) <= date('2019-01-10')

Inexact searching for nearest time value

I'm looking for a programmatically and syntactically efficient way to go about searching for a value based on a Timestamp. Essentially I want to find the closest timestamp match...
Say for example in a MySQL table I have:
ID TIME Blob
1 4:03:10 abc
2 4:04:30 def
3 4:04:45 ghi
And I want to query this table based on the time 4:04:40. I would want to return record ID #3... If I searched for 4:04:35 I would want to return ID #2... How do I go about implementing this? I have many millions of rows in this table and I was thinking something like levenshtein dist will be too slow..?
Cheers!
How about:
SELECT id, MIN(ABS(time(time) - time("4:04:35"))) FROM table
Bear with me, I'm more used to Oracle where dates can be manipulated exactly like numbers if necessary, but I think you should look for the row that has the date with the smallest difference to your search date. The difference could be positive or negative so ABS() will be needed to take care of that.
How about
SELECT table.id,
ABS(TIMESTAMPDIFF(SECOND, table.time, [datetime.now])) as difference
FROM table
If that looks OK you then have to select the ID that has the minimum [difference]
SELECT MIN(time) FROM table WHERE TIME > [datetime.now]

storing dates in mysql

Is it better to store dates in mysql in three columns or use just one column. Which one is faster. Also, if I just want to do inserts with todays date in format dd/mm/yy , how do I do that. and also how do I do selects with that. Also, lets say if I wanted to get results for all the wednesdays, how do I do that or lets say one date 25th of all the months and years, how do i do that.
Thanks People.
I am using PHP with Apache and Mysql.
What are the drawbacks of using the structure that I am proposing. I can easily get all the 25th by using the date table and I can get all the days using another column for days. How much difference would be there in the terms of speed between my proposed solution and using a DATE table?
You will want to use a proper column type, such as DATE, DATETIME, or TIMESTAMP, depending on your needs. They are built specifically to handle dates, and can more easily perform other functions (adding, comparing, etc.) that would be difficult to perform on 3 separate columns.
Read this for more info.
DAYOFWEEK(date) will give you a numeric representation for the day. In your case, 4 = Wednesday. DAYOFMONTH(date) will work for finding all 25th days of the month.
DAYNAME(date) will return the name of the weekday for date
Also, if I just want to do inserts with todays date in format dd/mm/yy ,how do I do that.
Well it depends on the format your date is passed in through your
form but you are going to want to store your date in YYYY-mm-dd format.
INSERT INTO my_table (timefieldname) VALUES ( '$date' );
and also how do I do selects with that.
SELECT timefieldname FROM my_table;
//or you can format the date - this will give you month/day/year 01/01/2012
SELECT DATE_FORMAT(timefieldname, '%m/%d/%Y') FROM my_table;
Also, lets say if I wanted to get results for all the wednesdays,
SELECT timefieldname FROM my_table WHERE DAYNAME(timefieldname) = 'Wednesday';
How do I do that or lets say one date 25th of all the months and years, how do i do that.
SELECT timefieldname FROM my_table WHERE DAY(timefieldname) = '25';
You can free up having to pass dates from your codebase and let mysql insert them for you, provided they are time stamps:
ALTER TABLE tablename ADD `timefieldname` TIMESTAMP ON UPDATE CURRENT_TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ;
It's not much of a speed boost, but it does reduce your need to code and validate variables passed to the database.

MySql Query Grouping by Time

I am trying to create a report to understand the time-of-day that orders are being placed, so I need to sum and group them by time. For example, I would like a sum of all orders placed between 1 and 1:59, then the next row listing the sum of all orders between 2:00 and 2:59, etc. The field is a datetime variable, but for the life me I haven't been able to find the right query to do this. Any suggestions sending me down the right path would be greatly appreciated.
Thanks
If by luck it is mysql and by sum of orders you mean the number of orders and not the value amount:
select date_format(date_field, '%Y-%m-%d %H') as the_hour, count(*)
from my_table
group by the_hour
order by the_hour
This king of grouping (using a calculated field) will certainly not scale over time. If you really need to execute this specific GROUP BY/ORDER BY frequently, you should create an extra field (an UNSIGNED TINYINT field will suffice) storing the hour and place an INDEX on that column.
That is of course if your table is becoming quite big, if it is small (which cannot be stated in mere number of records because it is actually a matter of server configuration and capabilities as well) you won't probably notice much difference in performance.