apply an if condition in a sql query - mysql

i want to use a if condition in a sql query according to following need.
"if a year field is null then do not calculate age and if it is set then it have to execute.
here is my query.where is the problem?please consider this scenario
'if month and date is there like for example 0000-03-12'
SELECT id, name, birth_date, birth_time,
city_native, country_native, sex,
city_current, country_current, image,
if(YEAR(birth_date)='','',YEAR(CURDATE()) - YEAR(birth_date) -
(RIGHT(CURDATE(),5) < RIGHT(birth_date,5)),'') AS age
FROM birth_user u
WHERE <condition>;

You can use IFNULL() to check birth_date is NULL
CASE WHEN IFNULL(birth_date,0)=0 THEN '' ELSE YEAR(CURDATE()) - YEAR(birth_date) END as age

If your need is "if it is null", why are you comparing it to zero?
if(birth_date is null, 0, YEAR(CURDATE()) - ......) AS age
Where that 0 there is a suitable "default age".

Use NULL instead of 0000
SELECT id, name, birth_date, birth_time,
city_native, country_native, sex,
city_current, country_current, image,
if(birth_date is null,'',YEAR(CURDATE()) - YEAR(birth_date) -
(RIGHT(CURDATE(),5) < RIGHT(birth_date,5)),'') AS age
FROM birth_user u
WHERE " . implode(' AND ', $where);

Related

Validating age using a function in MySQL

so i'm having some issues using a function in SQL where i calculate the age given a certain date. The thing is that i need to validate with the current date and the date of birth if it's already the year or not.
For example the date i have in a register is 1994-11-15 and when consulting the information with
select EmployeeID Num_Emloyee, concat(FirstName, " . ", LastName) Name_Employee, Title Puesto, fn_Age(BirthDate) Edad, fn_Age(HireDate) WorkYears
from employees;
It returns 24, however if i only consult with select the function it returns 23, the correct answer.
At the moment this is the function i'm using to validate the age is this:
create function fn_Age(dateVal date)
returns int
begin
declare age int;
if day(now()) and month(now()) >= day(dateVal) and month(dateVal) then
set age=year(now())-year(dateVal);
else
set age=(year(now())-year(dateVal)) - 1;
end if;
return age;
end
Is there anything i'm not considering in the function?
day(now()) and month(now()) >= day(dateVal) and month(dateVal)
This logic doesn't make sense. I don't know if an if supports tuples in MySQL. If so, you can do:
(month(now()), date(now())) >= ( month(dateval), day(dateval) )
(this works in a MySQL WHERE clause.)
You can also do:
month(now()) * 100 date(now()) >= month(dateval) * 100 + day(dateval)
You can also use timestampdiff-function
select timestampdiff(year, '1994-11-15', now());

Stored procedure WHERE dynamically checking if param NAME is null OR has value

What is the most efficient way to create a dynamic sp where im checking the param NAME either its null or has value.
my GOAL here is to select the specific name and their datas else just display all name with datas if param NAME is null or has no value submitted.
Here's my 2 solution:
option 1
IF (SELECT call_transactions.`called_name` IS NULL FROM call_transactions) THEN
SELECT a.`called_name` , DATE_FORMAT(a.`start_datetime`,"%m/%d/%Y %T") AS start_datetime , DATE_FORMAT(a.`end_datetime`,"%m/%d/%Y %T") AS end_datetime, SEC_TO_TIME(a.`duration`) AS duration
FROM call_transactions a
WHERE a.`user_id` = pUSERID AND a.duration <> 0 AND DATE_FORMAT(a.start_datetime , "%m/%d/%Y") BETWEEN pSTART AND pEND
ORDER BY a.start_datetime DESC;
ELSE
SELECT a.`called_name` , DATE_FORMAT(a.`start_datetime`,"%m/%d/%Y %T") AS start_datetime , DATE_FORMAT(a.`end_datetime`,"%m/%d/%Y %T") AS end_datetime, SEC_TO_TIME(a.`duration`) AS duration
FROM call_transactions a
WHERE a.`user_id` = pUSERID AND a.called_name = pNAME AND a.duration <> 0 AND DATE_FORMAT(a.start_datetime , "%m/%d/%Y") BETWEEN pSTART AND pEND
ORDER BY a.start_datetime DESC;
END IF;
option 2
SELECT a.`called_name` , DATE_FORMAT(a.`start_datetime`,"%m/%d/%Y %T") AS start_datetime , DATE_FORMAT(a.`end_datetime`,"%m/%d/%Y %T") AS end_datetime, SEC_TO_TIME(a.`duration`) AS duration
FROM call_transactions a
WHERE a.`user_id` = pUSERID AND (a.called_name = pNAME OR pNAME = '') AND a.duration <> 0 AND DATE_FORMAT(a.start_datetime , "%m/%d/%Y") BETWEEN pSTART AND pEND
ORDER BY a.start_datetime DESC;
Thank you in advance for the enlightenment guys. Just a curious kid here
Use your 2nd option, but test for the correct value.
WHERE a.`user_id` = pUSERID
AND (pNAME IS NULL OR a.called_name = pNAME)
AND a.duration <> 0 AND DATE_FORMAT(a.start_datetime , "%m/%d/%Y") BETWEEN pSTART AND pEND
In the second condition, note that I reversed the terms.
This is not strictly necessary, because the optimizer should prune away whichever condition is unnecessary, but this makes your short-circuit intentions clear.
Note also that NULL is not equivalent to empty string, and nothing is equal to NULL, so IS NULL should be used if NULL is what you are matching against.
I don't know what you're doing with DATE_FORMAT() here, but don't do that.
Use correct datetimes everywhere, or use STR_TO_DATE() to convert the parameters, not DATE_FORMAT() against the column. You can't compare mm/dd/yyyy "between" two values. That doesn't make sense. 12/09/2010 is "between" 12/08/2017 and 12/10/2017 because your code is comparing strings, lexcally, not comparing dates.
As a rule, you should never use a column as an argument to function in WHERE because this defeats any indexes on the column and forces a full scan.

Mysql and between\in range condition

We have x2 columns min and max. Each can be null or integer. When we start search throw table we cannot use BETWEEN command... Question is, how to find in range with this conditions
value is greater then min (if it's not null)
and
value is less then max (if it's not null)
and
value is in range of min and max (if they BOTH not null)
value - our integer number. As you can see we cannot use BETWEEN command.
So NULL means no limit. You can still use BETWEEN:
select *
from mytable
where #value between coalesce(minvalue, #value) and coalesce(maxvalue, #value);
Or simply AND:
select *
from mytable
where #value >= coalesce(minvalue, #value)
and #value <= coalesce(maxvalue, #value);
Or the very basic AND and OR:
select *
from mytable
where (#value >= minvalue or minvalue is null)
and (#value <= maxvalue or maxvalue is null);
Use this:
WHERE col BETWEEN COALESCE(min, -2147483648) AND COALESCE(max, 2147483647)
According to your logic, if either the min or max be NULL, then the restriction should be ignored. In the above WHERE clause, if min be NULL then col will always be greater than the lower boundary, assuming that col is an integer. Similar logic applies to the max condition.
The large (and small) numbers you see represent the largest and smallest possible values for an integer in MySQL.
Without the option of using BETWEEN, I would recommend using a simple WHERE-AND clause.
If null values are not allowed, you should use the COALESCE function
http://dev.mysql.com/doc/refman/5.7/en/comparison-operators.html#function_coalesce
Returns the first non-NULL value in the list, or NULL if there are no non-NULL values.
SELECT *
FROM SCORES
WHERE score >= COALESCE(min_score, score)
AND score <= COALESCE(max_score, score)
Here is a sample fiddle I created
http://sqlfiddle.com/#!9/306947/2/0
My solution Yii2 AR like
$query
->joinWith(['vacancySalary'])
->andWhere([
'and',
'IF (vacancy_salary.min IS NULL, ' . $this->salaryMin . ', vacancy_salary.min) >= ' . $this->salaryMin,
'IF (vacancy_salary.max IS NULL, ' . $this->salaryMin . ', vacancy_salary.max) <= ' . $this->salaryMin
]);
Simple answer is use IF condition and proper values.
ADDED:
Another way to go
$query
->joinWith(['vacancySalary'])
->andWhere($this->salaryMin . ' BETWEEN IF(vacancy_salary.min IS NULL, 0, vacancy_salary.min) AND IF(vacancy_salary.max IS NULL, 0, vacancy_salary.max)');

Age Calculation duplicate column using sql server 2008 R2

I have login table with DOB Column. I need duplicate column for age. But i can't do this. I can convert DOB column convert to Age for alone
`SELECT FLOOR(DATEDIFF(DAY,'10/10/1990' , getdate()) / 365.25)` works fine.
But I need to convert whole column.
If I'm Using
SELECT FLOOR(DATEDIFF(DAY,Select DOB From login_tbl , getdate()) / 365.25) like this,
It's throwing error. How can I get it?
Thankyou
Your approach will get wrong result in such cases below:
declare #now date
set #now = '11/10/2014'
select
FLOOR(DATEDIFF(DAY,'11/10/2013' , #now) / 365.25) -- should be 1 but will get 0
, FLOOR(DATEDIFF(DAY,'11/10/2012' , #now) / 365.25) -- should be 2 but will get 1
, DATEDIFF(DAY,'11/10/2013' , #now)
, DATEDIFF(DAY,'11/10/2012' , #now)
My suggestion is :
declare #now date
set #now = '11/10/2014'
select (convert(int,convert(varchar(8), #now ,112))
- convert(int,convert(varchar(8),convert(date,'11/10/2013'),112) ) )/10000
You could see my explain in this answer.
So for your login_tbl you could:
select
DOB, (convert(int,convert(varchar(8), DOB ,112))
- convert(int,convert(varchar(8),convert(date,'11/10/2013'),112) ) )/10000 as AGE
from
login_tbl
select trunc((trunc(sysdate) - to_date('16-mar-2010', 'dd-mon-yyyy'))/ (365.23076923074))
from dual

Stuffing multiple rows to see if columns are populated?

I'm trying to figure out a way in MySql to stuff multiple records for the same user into a single row to see which columns are populated. For example:
Username Height Weight Age
Bob123 6ft
Bob123 100lbs
Bob123 120lbs 25yrs
Let's say I have these three records in a table. I want to be able to combine them into a single row that just indicates if each column was populated in any of the records. My hopeful result record would look something like this for each user:
Username Height Weight Age
Bob123 True True True
Is there a way to do this in MySQL or do I need to look at doing this programmatically?
A generic sql method would be like this:
select username
, case when maxheight is not null then 'true' else 'false' end hasheight
, etc
from
(select username
, max(height) maxheight
, etc
from yourtables
where whatever
group by username) temp
CREATE TABLE person (Username VARCHAR(55), Height VARCHAR(55), Weight VARCHAR(55) , Age VARCHAR(55)
);
INSERT INTO person VALUES
('Bob123' , '6ft' , NULL , NULL),
('Bob123' , NULL , '100lbs' , NULL),
('Bob123' , NULL , '120lbs' , '25yrs');
SELECT username,
CASE height WHEN NULL THEN ' ' ELSE 'True' END,
CASE weight WHEN NULL THEN ' ' ELSE 'True' END,
CASE age WHEN NULL THEN ' ' ELSE 'True' END
FROM person
GROUP BY username;
DEMO