Conditionally update column from another column in same table - mysql

I've looked through SO, and there are similar questions, but I can't seem to figure out how to do what I need.
For the purposes of this question, my table has 3 columns: reconciled (tinyint), datereconciled (timestamp, CAN BE NULL), and dateadded (timestamp).
For my code logic, if reconciled==1, there should be a timestamp in datereconciled, but I recently noticed that wasn't always happening. Fixed the code, but now have a lot of NULL values in datereconciled where there should be a timestamp. So, for all rows where reconciled==1 AND datereconciled==NULL, I would like to "update" the value FROM dateadded INTO datereconciled. If there is already a timestamp in datereconciled, leave it alone. And leave it alone if reconciled==0.

You should be able to use a simple update:
UPDATE YourTable
SET DateReconciled = DateAdded
WHERE DateReconciled IS NULL
AND reconciled = 1;

You basically wrote the query already
UPDATE table SET datereconciled = dateadded
WHERE reconciled = 1
AND datereconciled IS NULL

I figured I'd have to use a select in my update query, so I'm a victim of over-complicating things! However, here is my overly complicated self-discovered answer prior to the answers provided:
UPDATE
`transactions` AS `dest`,
(
SELECT
*
FROM
`transactions`
WHERE
`reconciled` = 1 AND `datereconciled` IS NULL
) AS `src`
SET
`dest`.`datereconciled` = `src`.`dateadded`
;

Related

using SET with FROM in mysql. Attaching my query below can anyone help me with it

whats wrong in below query syntax? How can we properly use SET to update column values from one q_id to another q_id.
UPDATE answer
SET
expiry = newdata.expiry
FROM
(
SELECT
expiry,
q_id,
created_at,
seller_id
FROM answer
WHERE
q_id=49
and status='APPROVED'
and expiry is not NULL
and expiry < '2028-01-01 00:00:00'
) newdata
WHERE
q_id=343
AND created_at = newdata.created_at
AND seller_id = newdata.seller_id
There is no FROM clause in UPDATE syntax in MySQL.
UPDATE answer
JOIN
(
SELECT
expiry,
-- q_id, -- excess, it is not used in outer query
created_at,
seller_id
FROM answer
WHERE
q_id=49
and status='APPROVED'
-- and expiry is not NULL -- excess due to the next condition
and expiry < '2028-01-01 00:00:00'
) newdata USING (created_at, seller_id)
SET
answer.expiry = newdata.expiry
WHERE
answer.q_id=343;
Pay attention - the subquery may return more than one row per (created_at, seller_id) value. In this case the value from one indefinite row from all of them will be used for updating. So GROUP BY and MIN/MAX needed in the subquery for the whole query to be deterministic.

Case in list - Tableau

I'm trying to filter out a huge amount of data out so i decided to create a calculated field and using case if product_id in the list then '1' else '0'
but for some reason it though syntax error.
this is my calculated field:
CASE when product_id in (
'31049','31048','26166','27816','26031','28861','28864','28863','28203','28110','20641','38112','45174','20645','28404','20646','20648','26159','33287','31417','40551','41020','40550','40550','40553','40554','29804','29941','31430','33354','36730','26073','31432','31433','31431','38154','38166','26029','28341','45138','38069','42069','26060','26060','33886','33886','28392','29518','44879','20651','20655','42914','37535','28031','27588','29297','37688','37709','29551','29551','30183','29550','26187','29549','41348') THEN '1' ELSE '0'
END
Any idea who it should be written?
Thanx in advance :)
On a sample dataset this works:
SELECT RIDE_ID as ri,
CASE
WHEN ri in ('5EB0FAD625CFAEAB', '5A9314E3AF8DCC30') THEN '1'
ELSE '0'
END AS result
FROM CITIBIKE_TRIPS LIMIT 10;
I get:
yes it works in the database but not in Tableau :) I couldn't run it in a calculated field
Maybe using LATERAL would allow to run it from Tableau:
CREATE OR REPLACE TABLE t(ID INT, product_id TEXT);
INSERT INTO t VALUES (1, '31049'),(2,'31048'), (3, '100');
SELECT *
FROM t
,LATERAL (SELECT CASE WHEN t.product_id IN ( '31049','31048','26166','27816'/*...*/)
THEN '1' ELSE '0' END) AS s(result);
One option— create a table with your keys that you wish to filter, and then use a join to let the database do the work. Could be easier to maintain. Likely more efficient
Another option is to create a set in Tableau based on the product_id field. Define that set by checking the product ids you wish, and then place the set of the filter shelf to filter to either include or exclude the product_ids in your set.

MYSQL - COUNT() NULL Values

This has been racking my head. I've scoured the internet (including this place) and can't find a solution. So as a last resort I was hoping the good people of this forum might be able to help me out.
I have two tables:
TableA
Order_detailsID
OrderID
TitleID
Return_date
TableB
TitleID
Title_name
Quantity_in_stock
And would like to run a query that shows the remaining 'Quantity_in_stock'.
If the 'Return_date' is set to NULL then it means the item is currently out -- so I have been trying to use the count() function for the NULL values and subtract it from the 'Quantity_in_stock'.
This is the script I have so far:
DELIMITER //
CREATE PROCEDURE InStock()
BEGIN
Select TableB.TitleID,
TableB.Title_name,
TableB.Quantity_in_stock AS 'Total_Stock',
COUNT(TableA.return_date IS NULL) AS 'Rented_Out',
TableB.Quantity_in_stock - COUNT(TableA.return_date IS NULL) AS 'Remaining Stock'
From TableB
LEFT JOIN TableA
ON TableA.TitleID = TableB.TitleID
GROUP BY TableB.TitleID;
END//
This works if there is one of more of the TitleIDs at NULL, however if there are no values at NULL, then the Count() is still returning a value of 1 when it should be 0.
What am I doing wrong?
Instead of:
COUNT(TableA.return_date IS NULL)
use this:
SUM(CASE
WHEN TableA.TitleID IS NULL THEN 0
WHEN TableA.return_date IS NOT NULL THEN 0
ELSE 1
END)
The problem with the TableA.return_date IS NULL predicate is that it's true in two completely different situations:
When there is no matching record in TableA
When there is a matching record but TableA.return_date value of this exact record is NULL.
Using the CASE expression you can differentiate between these two cases.
I will like to mention a simple concept here, just keep counting the rows when that particular column is null.
select count(*) from table_name where column_name is null

How to update a column based on comparison result on another column

I can easily locate the rows I want with these sql statements:
SELECT COUNT(*) FROM `individuals` WHERE `company_zip` != '';
SELECT COUNT( * ) FROM `individuals` WHERE length( `company_zip` ) > 0;
SELECT COUNT( * ) FROM `individuals` WHERE strcmp( `company_zip`, '' ) != 0;
And there are probably 100 other ways to do this.
However...
Try using these in an UPDATE statement
UPDATE `individuals` SET `company_country` = 1 WHERE `company_zip` != '';
UPDATE `individuals` SET `company_country` = 1 WHERE length( `company_zip` ) > 0;
UPDATE `individuals` SET `company_country` = 1 WHERE strcmp( `company_zip`, '' ) != 0;
And I get responses like this:
0 row(s) affected. ( Query took 0.5920 sec )
I admit I am tired from looking at manual pages and google searches to figure this out. Which mysql principle am I missing here? It is easy to count the lines in SELECT statement but same criteria does not work for UPDATE statement. Is this a bug?
Darn! I figured it out just before posting. So I will give anyone wondering the answer.
I accidentally added field company_country with default value of 1 and so all records got default value of '1'. So mysql was trying to update fields, but found that they already were set to 1. Blanking them out allowed UPDATE queries to work. Nevermind. Posting for anyone who makes similar error.
Bradley
OK. To be specific, because all records already had field 'company_country' set to 1, mysql was telling me in a terse way, that it had not UPDATEd or changed any of the records. They started out with that field set to 1, and ended up with that field set to 1. Check your defaults people, especially is someone else set up the table. I could have typed
UPDATE `individuals` SET `company_country` = 1;
and the answer would still have been the same. 0 row(s) affected.

MySQL : selecting the X smallest values

Let be a table like this :
CREATE TABLE `amoreAgentTST01` (
`moname` char(64) NOT NULL DEFAULT '',
`updatetime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`data` longblob,
PRIMARY KEY (`moname`,`updatetime`)
I have a query to find the oldest records for each distinct 'moname', but only if there are multiple records for this 'moname' :
SELECT moname, updatetime FROM amoreAgentTST01 a
WHERE (SELECT count(*) FROM amoreAgentTST01 x WHERE x.moname = a.moname) > 1
AND a.updatetime = (SELECT min(updatetime) FROM amoreAgentTST01 y WHERE y.moname = a.moname) ;
My question is : how to do the same but selecting the X oldest values ?
I now simply run this, delete the oldest values and rerun it... which is not so nice.
Seconds question is : what do you think of the above query ? can it be improved ? is there any obvious bad practice ?
Thank you in advance for your advices and help.
Barth
Would something like this work (untested):
SELECT moname, MIN(updatetime) FROM amoreAgentTST01
GROUP BY moname HAVING COUNT(moname)>1
Edit - the above is meant only as a replacement for your existing code, so it doesn't directly answer your question.
I think something like this should work for your main question:
SELECT moname, updatetime FROM amoreAgentTST01
GROUP BY moname, updatetime
HAVING COUNT(moname)>1
ORDER BY updatetime LIMIT 0, 10
Edit - sorry, the above won't work because it's returning only 10 records for all the monames - rather than the 10 oldest for each. Let me have a think.
One more go at this (admittedly, this one looks a bit convoluted):
SELECT a.moname, a.updatetime FROM amoreAgentTST01 a
WHERE EXISTS
(SELECT * FROM amoreAgentTST01 b
WHERE a.moname = b.moname AND a.updatetime = b.updatetime
ORDER BY b.updatetime LIMIT 0, 10)
AND (SELECT COUNT(*) FROM amoreAgentTST01 x WHERE x.moname = a.moname) > 1
I should add that if there is an ID column - generally the primary key- then that should be used for the sub-query joins for improved performance.