Select Query Works, Delete Doesn't? - mysql

I have developed a query to purge all but the most recently added row, based on a field -> Timestamp that is stored as text, and a User ID field.
Also involved is a changing date format, so some coalescing is involved as well.
Here is the delete query ->
DELETE
FROM `table` main
WHERE COALESCE(STR_To_DATE( main.Timestamp , '%a %b %d %H:%i:%s CDT %Y' ), STR_To_DATE( main.Timestamp , '%a %b %d %H:%i:%s CST %Y' )) <
(SELECT MAX(COALESCE(STR_To_DATE( sub.Timestamp , '%a %b %d %H:%i:%s CDT %Y' ), STR_To_DATE( sub.Timestamp , '%a %b %d %H:%i:%s CST %Y' )))
FROM `table` sub
WHERE sub.Retrieving_User = main.Retrieving_User )
This doesn't run, throwing this error ->
#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'main WHERE COALESCE(STR_To_DATE( main.Timestamp , '%a %b %d %H:%i:%s CDT %Y' ),' at line 2
I understand what this is, just not why it is occuring. If I change the query to a select ->
SELECT *
FROM `table` main
WHERE COALESCE(STR_To_DATE( main.Timestamp , '%a %b %d %H:%i:%s CDT %Y' ), STR_To_DATE( main.Timestamp , '%a %b %d %H:%i:%s CST %Y' )) <
(SELECT MAX(COALESCE(STR_To_DATE( sub.Timestamp , '%a %b %d %H:%i:%s CDT %Y' ), STR_To_DATE( sub.Timestamp , '%a %b %d %H:%i:%s CST %Y' )))
FROM `table` sub
WHERE sub.Retrieving_User = main.Retrieving_User )
it correctly grabs all the data I want to delete.
Please tell me I don't have to change the format of the query, because I've spent all morning on it. :(
EDIT:
I have found through research that you cannot delete from the same table you are using in your subquery. So I get to create a long workaround for this...will be updating later...

DELETE from `table` where COALESCE(STR_To_DATE( Timestamp , '%a %b %d %H:%i:%s CDT %Y' ), STR_To_DATE( Timestamp , '%a %b %d %H:%i:%s CST %Y' )) in
(
SELECT COALESCE(STR_To_DATE( main.Timestamp , '%a %b %d %H:%i:%s CDT %Y' ), STR_To_DATE( main.Timestamp , '%a %b %d %H:%i:%s CST %Y' ))
FROM `table` main
WHERE COALESCE(STR_To_DATE( main.Timestamp , '%a %b %d %H:%i:%s CDT %Y' ), STR_To_DATE( main.Timestamp , '%a %b %d %H:%i:%s CST %Y' )) <
(SELECT MAX(COALESCE(STR_To_DATE( sub.Timestamp , '%a %b %d %H:%i:%s CDT %Y' ), STR_To_DATE( sub.Timestamp , '%a %b %d %H:%i:%s CST %Y' )))
FROM `table` sub
WHERE sub.Retrieving_User = main.Retrieving_User)
)

Related

How can i do a condition join with IF statement

How would you do a inner join on a table where i need to filter the status, but on one of the status value, i need to perform an additional date comparison check on SQL phpmyadmin.
i have the following:
ex.
INNER JOIN orders backup_orders
ON backup_orders.bc_id = product_sold.order_id
AND backup_orders.status_id NOT IN (0, 1, 4, 6, 13, 14)
AND CONVERT_TZ( STR_TO_DATE( backup_orders.date_modified, "%a, %d %b %Y %T" ) , "GMT", "America/Chicago" )
>= CONVERT_TZ(STR_TO_DATE(:previous_week_start, "%a, %d %b %Y %T") , "GMT", "America/Chicago")
This only gets me the record where the order is cancelled and it was cancelled after the previous_week_start. I want all the records but if the status is 5 which is cancelled, perform the date comparison and if it was cancelled after the date then add it to the result.
#Edited:
AND(backup_orders.status_id NOT IN (0,1,4,6,13,14) OR (backup_orders.status_id = 5 AND CONVERT_TZ( STR_TO_DATE( backup_orders.date_modified, '%a, %d %b %Y %T' ) , 'GMT', 'America/Chicago' ) >= CONVERT_TZ(STR_TO_DATE("Thu, 11 Mar 2021 22:00:00 +0000", '%a, %d %b %Y %T') , "GMT", "America/Chicago")))
You can use case in where condition:
INNER JOIN orders backup_orders
ON backup_orders.bc_id = product_sold.order_id
and backup_orders.status_id NOT IN (0, 1, 4, 6, 13, 14)
AND (case when backup_orders.status_id =5 then
CONVERT_TZ( STR_TO_DATE( backup_orders.date_modified, "%a, %d %b %Y %T" ) , "GMT", "America/Chicago" )
>= CONVERT_TZ(STR_TO_DATE(:previous_week_start, "%a, %d %b %Y %T") , "GMT", "America/Chicago") end)
But wouldn't it better to compare backup_orders.status_id=5 directly instead of backup_orders.status_id NOT IN (0, 1, 4, 6, 13, 14)
If you examine the conditions in your edit, the date comparison never matters...
AND
(
backup_orders.status_id NOT IN (0,1,4,6,13,14)
OR
(
backup_orders.status_id = 5
AND
CONVERT_TZ( STR_TO_DATE( backup_orders.date_modified, '%a, %d %b %Y %T' ) , 'GMT', 'America/Chicago' )
>=
CONVERT_TZ(STR_TO_DATE("Thu, 11 Mar 2021 22:00:00 +0000", '%a, %d %b %Y %T') , "GMT", "America/Chicago")
)
)
If the status_id is 5, the first condition is True; 5 is NOT IN that list.
Then, it doesn't matter what the 2nd or 3rd conditions are, the result of TRUE OR (X AND Y) is True, no matter what X or Y are.
So, you need to add 5 to your list...
AND
(
backup_orders.status_id NOT IN (0,1,4,5,6,13,14) -- added 5 here
OR
(
backup_orders.status_id = 5
AND
CONVERT_TZ( STR_TO_DATE( backup_orders.date_modified, '%a, %d %b %Y %T' ) , 'GMT', 'America/Chicago' )
>=
CONVERT_TZ(STR_TO_DATE("Thu, 11 Mar 2021 22:00:00 +0000", '%a, %d %b %Y %T') , "GMT", "America/Chicago")
)
)
Now, a status of 5 can only resolve True if the date comparison Also resolves to True.
(Please forgive typos, I'm doing this on a phone.)

Convert a string to date (special format) in MySQL

I have a column 'birthDate' which returns a string value of [Day of the Week], [Month] [Day], [Year]
(e.g. Monday, December 30, 2013)
I am using SELECT STR_TO_DATE(birthDate, '%m/%d/%Y') but it returns a null value.
Any ideas?
SOLUTION
SELECT STR_TO_DATE(birthDate, '%W, %M %d, %Y')
You're showing one format of your date ([Day of the Week], [Month] [Day], [Year]) but using another in STR_TO_DATE ([Month]/[Day]/[Year]). You need to provide STR_TO_DATE with the format your column is currently in:
SELECT STR_TO_DATE(birthDate, '%W %m %d %Y')
If you want that result to be in a new format you can then use DATE_FORMAT():
SELECT DATE_FORMAT(STR_TO_DATE(birthDate, '%W %m %d %Y'), '%m/%d/%Y')

What is wrong in select str_to_date ( '%e %b %Y','14 Aug 1987' )

What is wrong in
select str_to_date ( '%e %b %Y','14 Aug 1987' )
I even tried '%d %b %Y'
Referred http://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html
because it is "STRING" to "DATE" ... put the string first ...
select str_to_date ( '14 Aug 1987','%e %b %Y' )

MySQL IF with CONCAT AND DATE_FORMAT

I have the following statement, which returns empty values for 'label':
SELECT *,
IF (
`date_to` IS NULL,
CONCAT(DATE_FORMAT(`date_from`, '%D %M %Y'), ' ', `location`),
CONCAT(DATE_FORMAT(`date_from`, '%D %M %Y'), ' - ', DATE_FORMAT(`date_to`, '%D %M %Y'), ' ', `location`)
) AS `label`
FROM `courses`
ORDER BY `date_from` ASC
The date_from and date_to columns are both DATE types, and the second one might contain a default value of 0000-00-00.
Any idea what might be causing it?
DATE_FORMAT(cast('0000-00-00' as date), '%D %M %Y') returns NULL, therefore the entire CONCAT will also become null.
Perhaps you should also compare date_to to the value '0000-00-00' in the IF condition?

mysql date format with changing string value

I have a field called Timestamp, that stores its values as text as opposed to an actual Timestamp. The logging application is unchangeable, unfortunately.
So
table.Timestamp -> text field with format -> "Wed Mar 02 13:28:59 CDT 2011"
I have been developing a query to purge all but the most recent row using this as my Timestamp selector, which is also converting the string into a date ->
MAX( STR_To_DATE( table.Timestamp , '%a %b %d %H:%i:%s CDT %Y' )
My query works perfectly...
However, what I've found is that the string value -> 'CDT' -> changes between 'CDT' and 'CST' depending on whether the current time is daylight savings time or not. During daylight savings time, it logs as 'CDT', and vice versa.
So all the rows that contain 'CST' get ignored when I run this ->
MAX( STR_To_DATE( table.Timestamp , '%a %b %d %H:%i:%s CDT %Y' )
and all the rows that contain 'CDT' get ignored when I run this ->
MAX( STR_To_DATE( table.Timestamp , '%a %b %d %H:%i:%s CST %Y' )
Is there a way to make it run against both string formats?
EDIT -
So given the following data (different only by 'CDT and 'CST':
"Wed Mar 02 13:28:59 CDT 2011" and "Tue Mar 08 09:42:07 CST 2011"
Currently it will return as follows:
MAX( STR_To_DATE( table.Timestamp , '%a %b %d %H:%i:%s CDT %Y' ) Returns - Wed Mar 02 13:28:59 CDT 2011
MAX( STR_To_DATE( table.Timestamp , '%a %b %d %H:%i:%s CST %Y' ) Returns - Tue Mar 08 09:42:07 CST 2011
I want it to return "Tue Mar 08 09:42:07 CST 2011" no matter what.
EDIT 2:
This is my main query:
DELETE
FROM `table` main
WHERE STR_To_DATE( main.Timestamp , '%a %b %d %H:%i:%s CST %Y' ) <
(SELECT COALESCE(STR_To_DATE( sub.Timestamp , '%a %b %d %H:%i:%s CDT %Y' ), STR_To_DATE( sub.Timestamp , '%a %b %d %H:%i:%s CST %Y' ))
FROM `table` sub
WHERE sub.Retrieving_User = main.Retrieving_User )
Coalesce the two. COALESCE means to return the first non-null value in the set.
In this case it will first try to parse it using "CDT". If that fails, returning NULL, it will try to parse using "CST" instead. (If that fails, it will reach the end of the coalesce list and just return NULL, but in your case it won't get that far).
select MAX( COALESCE(STR_To_DATE( test.Timestamp , '%a %b %d %H:%i:%s CDT %Y' ), STR_To_DATE( test.Timestamp , '%a %b %d %H:%i:%s CST %Y' )))
from test
SQL Fiddle Try changing the data in the table and see it work.