comma separated list of string convert into date in mysql - mysql

I have 1 query as given below where a parameter with name "ListOfDate" which is coming by front end in form of string..i have "ENCOUNTERDATE" in mysql with datetime datatype..
SELECT d.encounterdate,
d.hospitalid,
amiop1,
amiop2,
amiop3,
amiop4,
amiop5,
amiop16
FROM factopami f,
dimpatientencounter d
WHERE d.hospitalid = 987654
AND d.measurecategory = 'AMI'
AND ( encounterdate IN ( ** listofdate ** )
OR encounterdate IS NULL )
AND d.patientid = f.patientid
AND d.id = f.patientencounterid
ORDER BY encounterdate;
after it i tried to convert ListOfDate into date:
SELECT d.encounterdate, d.hospitalid, amiop1, amiop2, amiop3, amiop4,
amiop5, amiop16
FROM factopami f, dimpatientencounter d
WHERE d.hospitalid = 987654
AND d.measurecategory = 'AMI'
AND ( encounterdate IN (str_to_date ('01-10-2012' '%m-%d-%Y'))
OR encounterdate IS NULL
)
AND d.patientid = f.patientid
AND d.ID = f.patientencounterid
ORDER BY encounterdate;
which is working for single string ...but i got list of string which is giving me error..
SELECT d.encounterdate,
d.hospitalid,
amiop1,
amiop2,
amiop3,
amiop4,
amiop5,
amiop16
FROM factopami f,
dimpatientencounter d
WHERE d.hospitalid = 987654
AND d.measurecategory = 'AMI'
AND ( encounterdate IN ( Str_to_date('01-10-2012', '01-10-2012',
'%m-%d-%Y') )
OR encounterdate IS NULL )
AND d.patientid = f.patientid
AND d.id = f.patientencounterid
ORDER BY encounterdate;
LIMIT 0, 1000 Error Code: 1582. Incorrect parameter count in the call to native function 'STR_TO_DATE' 0.000 sec
so how can i convert it to on mysql level

In short - at the moment you're converting the list to:
(encounterdate IN ( STR_TO_DATE('01-10-2012','01-10-2012', '%m-%d-%Y'))
Instead, you need to convert it to:
( encounterdate IN ( STR_TO_DATE('01-10-2012', '%m-%d-%Y')
, STR_TO_DATE('01-10-2012', '%m-%d-%Y') )
As more of an explanation, the IN operator is expecting a list of things:
encounterdate IN ( thing1, thing2, thing3 )
The thing you are passing is a date, meaning you're doing this:
encounterdate IN ( date1, date2, date3 )
Alas, you have strings instead of dates, and so you need to convert each of those strings into dates. Thus you need to some conversions.
date1 needs to be STR_TO_DATE( string1, '%m-%d-%y )
date2 needs to be STR_TO_DATE( string2, '%m-%d-%y )
date3 needs to be STR_TO_DATE( string3, '%m-%d-%y )
Putting that all together, you need to generate:
encounterdate IN ( STR_TO_DATE('01-10-2012', '%m-%d-%Y')
, STR_TO_DATE('01-10-2012', '%m-%d-%Y')
, STR_TO_DATE('01-10-2012', '%m-%d-%Y')
As an alternative, if you feel it's not possible to produce this, you could flip the conversion round and instead convert the encounterdate column to a string using DATE_FORMAT as you do the comparison.
Documentation here:
http://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html#function_date-format
http://www.w3schools.com/sql/func_date_format.asp
This would result in:
DATE_FORMAT( encounterdate, '%m-%d-%Y' ) IN ( '01-10-2012'
, '01-10-2012'
, '01-10-2012' )
However, you should bear in mind that this will have an impact on the indexing of encounterdate, though this might not be a problem in your use-case.

As it is explained in mysql manual, str_to_date function , get only to parameters. The first parameter is your date string, and the second one is the format of your date string.so you cann't use it like this:
STR_TO_DATE('01-10-2012','01-10-2012', '%m-%d-%Y')
You should use this:
STR_TO_DATE('01-10-2012', '%m-%d-%Y'),STR_TO_DATE('01-10-2012', '%m-%d-%Y')

Related

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.

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

How to convert a string to a number in the where statement

I am trying to convert a string to a number. I have values stored like $4,215.35 so I want to convert that to a number so I can check if the value is greater than 50 or not.
If the value is greater than 50 then I want to update a field called first_sale_on with a time stamp.
Here is what I have done
UPDATE
account AS m
INNER JOIN ps_weekly_activations AS t ON t.mid = m.mid
SET
m.first_sale_on = CAST(CONCAT(STR_TO_DATE(t.Date_First_PL_Sale, '%c/%e/%Y'), ' 00:00:00') AS datetime)
WHERE
t.Date_First_PL_Sale IS NOT NULL
AND CONVERT(REPLACE(REPLACE(Private_Label_Net_Sales, '$',''), ',', ''), DECIMAL(18,2) ) >= 50;
I get the following error:
"Error code 1366: Incorrect decimal value '' at row -1..
The error means that I am trying to do operation on a string in the where statement. but I am not sure why the conversion is failing here. If the convert works then the query should execute with no problems.
I found the problem and the solution. The problem is that there was a bad data in that table that was throwing the query off.
To solve it I have added a check print i do the arithmetic. the check will check if the value is a number or not
This my new query (I hope my answer helps someone else)
UPDATE
account AS m
INNER JOIN ps_weekly_activations AS t ON t.mid = m.mid
SET
m.first_sale_on = CAST(CONCAT(STR_TO_DATE(t.Date_First_PL_Sale, '%c/%e/%Y'), ' 00:00:00') AS datetime)
WHERE
t.Date_First_PL_Sale IS NOT NULL
AND CONCAT('', REPLACE(REPLACE(Private_Label_Net_Sales, '$',''), ',', '') *1 ) = REPLACE(REPLACE(Private_Label_Net_Sales, '$',''), ',', '')
AND CONVERT(REPLACE(REPLACE(Private_Label_Net_Sales, '$',''), ',', ''), DECIMAL(18,2) ) >= 50;

MySQL DATE_SUB not working with a variable but working with a regular value

I have this part of a query:
(#tmpo1245 := CAST( ( ( pm5.`meta_value` - pm4.`meta_value` ) / 86400 ) AS SIGNED ) ) AND
(#mutdate:=DATE_SUB( '2011-06-1', INTERVAL #tmpo1245 DAY ) ) AND
Which is causing my query to fail. I know CAST( ( ( pm5.meta_value- pm4.meta_value) / 86400 ) AS SIGNED ) is 5, I put it in a select statement to test it. I also know the following query works just fine:
(#tmpo1245 := 5 ) AND
(#mutdate:=DATE_SUB( '2011-06-1', INTERVAL #tmpo1245 DAY ) ) AND
What is going on?
It seems the error is with the clause inside the CAST in your query. I guess the data types of pm5.meta_value and pm4.meta_value your are trying to subtract are not numeric. Hence please cast them decimals first before subtracting. Example code would be as follows.
#tmpo1245 := CAST( ( (
CAST( pm5.`meta_value` AS DECIMAL) - CAST( pm4.`meta_value` AS DECIMAL)) / 86400 )
AS SIGNED )

Getting last months data from the database

My query currently gets yesterdays data but I now want to get all of last months data. (E.g.from 1st to 31st)
$res = mysql_query("SELECT
FROM_UNIXTIME( enquiry_time ), `id` ,
`fullname` , `address1` , `citytown` ,
`postcode` , `telno` ,
`property_value` ,`total_secured_debt`
, `email` , `on_market` , `agent` ,
`reason` , `price_concession` ,
`asking_price` , `form_page` FROM
$table WHERE TO_DAYS(FROM_UNIXTIME( enquiry_time )) = (TO_DAYS(NOW())-1)
");
There is not a TO_MONTHS so im not sure where to start!
Try:
$res = mysql_query("
SELECT FROM_UNIXTIME(`enquiry_time`), `id`, `fullname`, `address1`,
`citytown`, `postcode`, `telno`, `property_value`, `total_secured_debt`,
`email`, `on_market`, `agent`, `reason`, `price_concession`,
`asking_price`, `form_page`
FROM $table
WHERE YEAR(FROM_UNIXTIME(`enquiry_time`)) = YEAR(CURDATE() - INTERVAL 1 MONTH)
AND MONTH(FROM_UNIXTIME(`enquiry_time`)) = MONTH(CURDATE() - INTERVAL 1 MONTH)
");
This would all work vastly better and faster if enquiry_time were a native DATE or DATETIME field, with an index, instead of a Unix timestamp.
Looking for function MONTH?
That will work (like your TO_DAYS does now), but remember you may be paying a hefty performance price if the table is large: MySQL can't use an index when the WHERE condition depends on a function rather than directly on the indexed column (use EXPLAIN to see the query plan and confirm that this is the case). Performance-wise, you're better off computing the lower and upper bound of the times you want to see (with functions and arithmetic on NOW()) and then using a straight BETWEEN in your WHERE. Again, use EXPLAIN to double check -- trying to second guess MySQL's query optimizer is a sterile exercise, it's much easier to check on what it plans to do;-).
Could you use something like the following? I think it will get you what you want.
FROM_UNIXTIME(enquiry_time)
BETWEEN date_format(NOW() - INTERVAL 1 MONTH, '%Y-%m-01')
AND last_day(NOW() - INTERVAL 1 MONTH)
Here's the reference.
While chaos's answer will work, if $table is indexed by enquiry_time,
then it will be faster to compare against that field directly than against a function of it.
That transforms his answer into the even uglier:
$res = mysql_query("
SELECT FROM_UNIXTIME(enquiry_time), id, fullname, address1,
citytown, postcode, telno, property_value, total_secured_debt,
email, on_market, agent, reason, price_concession, asking_price,
form_page
FROM $table
WHERE enquiry_time >= UNIX_TIMESTAMP(concat(year(curdate() - interval 1 month), '-', month(curdate() - interval 1 month), '-01'))
AND enquiry_time < UNIX_TIMESTAMP(concat(year(curdate()), '-', month(curdate()), '-01'))
");
i see you are using php so this might be better than wrestling with mysql functions:
$end_of_month = strtotime(date('Y-m-01 00:00:00'))-1;
$start_of_month = strtotime(date('Y-m-01 00:00:00',$end_of_month));
$res = mysql_query("SELECT
FROM_UNIXTIME( enquiry_time ), `id` ,
`fullname` , `address1` , `citytown` ,
`postcode` , `telno` ,
`property_value` ,`total_secured_debt`
, `email` , `on_market` , `agent` ,
`reason` , `price_concession` ,
`asking_price` , `form_page` FROM'
$table WHERE enquiry_time >= '".$start_of_month."' AND enquiry_time <= '".$end_of_month."'
");