Update a field if another field has a certain value - mysql

I am trying to update a MySQL database but only if a field has the value Approved.
If status is Approved then Date approved should update with the date.
Below is the code I am currently using but cannot get it to work. How to get it to work?
UPDATE my_table
SET `FieldValue`= IF(FieldName='status' AND FieldValue='Approved','".date('m/d/Y')."','')
WHERE `SubmissionId`=".$SubmissionId."
AND FieldName='Date Approved'
Sample Data
+--------+--------------+---------------+--------------+
| FormId | SubmissionId | FieldName | FieldValue |
+--------+--------------+---------------+--------------+
| 6 | 778 | status | Not Approved |
| 6 | 778 | Date Approved | |
+--------+--------------+---------------+--------------+

Use a CASE statement like below:
UPDATE my_table
SET `FieldValue` = CASE WHEN FieldName = 'status'
AND FieldValue='Approved' THEN date('m/d/Y') ELSE `FieldValue` END
WHERE `SubmissionId` = $SubmissionId;
But your query won't make sense; your FieldValue column looks like a string type column and you are trying store a date type data.

Something like this?
$db = JFactory::getDbo();
$query = $db->getQuery(true);
// Fields to update.
$fields = array(
$db->quoteName('FieldValue') . ' = ' . $date->toSql('m/d/Y'))
);
// Conditions for which records should be updated.
$conditions = array(
$db->quoteName('SubmissionId') . ' = SubmissionId',
$db->quoteName('FieldValue') . ' = ' . $db->quote('Approved')
);
$query->update($db->quoteName('#__my_table'))->set($fields)->where($conditions);
$db->setQuery($query);
$result = $db->execute();

Superficially, you should be using the raw SQL like this:
UPDATE my_table
SET FieldValue = date('m/d/Y')
WHERE SubmissionId = 778
AND FieldName = 'Date Approved'
-- AND FieldValue IS NULL -- Optional
-- AND FormId = 6 -- Optional
AND EXISTS (SELECT * FROM my_table
WHERE FieldName = 'status'
AND FieldValue = 'Approved'
AND SubmissionId = 778
-- AND FormId = 6 -- Optional
)
You might need to tart things up a little to get values embedded into the string that forms the SQL statement.
You don't mention FormID in your query; in case of doubt, you should constrain the UPDATE with the correct FormID value, twice, like you constrain the SubmissionID value twice (as shown in the comments). You might decide you only want to update the 'Date Approved' field name when it is NULL (or perhaps blank).
I note that one of the problem with this EAV design is that you lose the type-checking that a normal design gives you. You could store a date (as intended), or a pure number, or pure text, or anything else in the FieldValue column for the 'Date Approved' FieldName and there's nothing to stop that abuse happening. If you had an orthodox typed column, you could ensure that non-dates were never stored in the 'Date Approved' column.
Your UPDATE is tied to a single submission ID; so is mine. It should be possible to enhance things so that all the uninitialized 'Date Approved' columns that are approved and have not previously had the 'Date Approved' value set do in fact have it set.

Related

WordPress query, meta_query, compare BETWEEN, no results

I have code for my filter. It worked well until I add new product in my database. I found the problem, but dont know what to do with that.
I have parameters "alc_min" and "alc_max" in my filter. I get these from crawling all products. After I send this filter, I fire this code:
$meta_query = array();
$b = "alc_min";
$c = "alc_max";
if (isset ( $data [$b] ) && isset ( $data [$c] )) {
$compare = "BETWEEN";
$a = array (
'key' => "alc",
'value' => array (
$data [$b],
$data [$c]
),
'compare' => $compare
);
array_push ( $meta_query, $a );
}
$items = new WP_Query ( array (
'post_type' => $type,
'posts_per_page' => $posts_per_page,
'order' => $order,
'meta_key' => $orderkey,
'orderby' => $orderby,
'post_status' => 'publish',
'meta_query' => $meta_query,
'paged' => $paged
) );
Until now, it worked well. No I add new product with "alc" <10 and I found, that if I have "alc_min" and "alc_max" <10 or >10, it is ok. But if "alc_min" is <10 and "alc_max" >10 I get no results at all.
Does anyone any idea what to check or fix?
After the clarification, I've suspected that the reason why selecting "alc_min" = 7 and "alc_max" = 13 doesn't yield any result is because of the column datatype. Consider this example:
CREATE TABLE table1 (
alc VARCHAR(50));
INSERT INTO table1 VALUES
('7'),
('9'),
('11'),
('13');
The table above is created with alc column datatype as VARCHAR instead of INTEGER (or numeric datatype). I've tested that running either one of the query below:
SELECT * FROM table1 WHERE alc BETWEEN '7' AND '9';
SELECT * FROM table1 WHERE alc BETWEEN '11' AND '13';
will return the expected result. However, with this query:
SELECT * FROM table1 WHERE alc BETWEEN '7' AND '13';
yields no result. This is because the values are treated as string instead of numbers and when that happens, 1 is always smaller than 7. See below what happen you run select query with order by on the data set above:
SELECT * FROM table1 ORDER BY alc;
+-----+
| alc |
+-----+
| 11 |
| 13 |
| 7 |
| 9 |
+-----+
As you can see, since the data is treated as string (according to the column datatype), then you could imagine this in alphabetical form as the following:
+-----+--------------+
| alc | alphabetical |
+-----+--------------+
| 11 | AA |
| 13 | AC |
| 7 | G |
| 9 | I |
+-----+--------------+
So, the condition of BETWEEN '7' AND '13' becomes BETWEEN 'G' AND 'AC'; which doesn't really make sense. And if you change to BETWEEN '11' AND '9' you'll get the correct result but that made the query even more confusing and not making sense at all.
Now, I've discovered that there are at least 3 workaround/solution for this:
One of the oldest way I can think of is by adding +0 to the column in the query. I didn't find any official docs about this but I assume that doing this will change the data value to numeric in the query:
SELECT * FROM table1
WHERE alc+0 BETWEEN '7' AND '13';
This is probably the same as above is just that I'm not sure if this is version specific or not. It turns out that in my testing, if you didn't wrap the searched value in quotes, you'll get the result as if the data is numeric:
SELECT * FROM table1
WHERE alc BETWEEN 7 AND 13;
This require a change of column datatype but afterwards any of the query with or without quotes on the searched value should work:
ALTER TABLE table1 CHANGE alc alc INT;
I hope that this is true and the issue is really about column datatype. As far as I know, this is the closest thing to what your situation is that I had experience with.
Here's a fiddle for reference

Update whole table in SQL?

I have a table called "customers" which looks like this:
ID | NAME | ADDRESS | ZIP
John | Peterson | Street 2 | 45738
Jan | 74383 | Street 4 | 74383
Eric | Stone | 74383 | 74383
Julia| Carry | Street 9 | 74383
I want to replace any occurrence of "74383" with "". I have about 1.5 Million rows. Is this doable?
Okay sorry that was my mistake, the number can be in any COLUMN! I updated it.
Assuming you mean in the zip column:
update customers
set zip = ''
where zip = '74383';
Note: you might prefer to set the value to NULL rather than the empty string (''), but your question explicitly suggests an empty string.
EDIT:
I would actually suggest that you use separate update statements for each column if you have indexes on them. The updates will be much faster.
Second, if you replace the value with NULL rather than '', you can use the logic:
update customers
set zip = NULLIF(zip, '74383'),
address = NULLIF(address, '74383'),
name = NULLIF(name, '74383')
where '74383' in (name, address, zip);
(You can actually replace this with an empty string using COALESCE(NULLIF(zip, '74383'), ''), but I prefer a CASE once the logic gets at all complicated.)
Reverse the IN operator to search the existence of '74383' value in all the columns then using case statement you can update the columns. Try this.
UPDATE customers
SET NAME = CASE WHEN NAME = '74383' THEN '' ELSE NAME END,
address = CASE WHEN address = '74383' THEN '' ELSE address END,
zip = CASE WHEN zip = '74383' THEN '' ELSE zip END
WHERE '74383' IN ( NAME, address, zip )
It is strange for me the requirement like this but, anyway, you can try this:
START TRANSACTION;
UPDATE customers
SET NAME = ''
WHERE NAME = '74383';
UPDATE customers
SET ADDRESS = ''
WHERE ADDRESS = '74383';
UPDATE customers
SET ZIP = ''
WHERE ZIP = '74383';
COMMIT;

mysql update table with values from another table?

I am trying to update my table 'supplier_stats' with the values from my other table 'supplier_change_request'.
My two tables look like the following:
Supplier_change_request
id | user_id | company_name | supplier_number
1 123 hewden V0001
Supplier_stats
Id | user_id | company_name | address | reference | supplier_number
1 123 pie n/a 12345 V0001
2 145 gates n/a 12345 V0002
Here is my MySQL:
$reference = '12345'
$query = "UPDATE supplier_stats
SET supplier_stats.company_name = (
SELECT supplier_change_request.company_name
FROM supplier_change_request
WHERE supplier_change_request.reference = '$reference' AND supplier_change_request.supplier_number = supplier_stats.supplier_number";
mysql_select_db('hewden1');
$retval = mysql_query( $query, $conn )
by my calculation this should be setting the value of company_name where supplier_number is 'V0001' in my table 'supplier_stats' to 'hewden'. However the company_name is not being updated.
Can someone please show me where I am going wrong? Thank you in advance
I think the syntax is a bit off in your query and that it should look like this (just the SQL, adapt to PHP as needed):
UPDATE supplier_stats ss
JOIN supplier_change_request scr ON scr.supplier_number = ss.supplier_number
SET ss.company_name = scr.company_name
WHERE ss.reference = '$reference'
The column reference pointed to the supplier_change_request in your sample query, but to supplier_stats in your sample data - I assumed the sample data was correct; change if not.
This query should change the company_name in supplier_stats from pie to hewden.

Select column names with their maximum data length MySQL

I have a table in mysql with many columns and I want to see maximum length of values. My purpose is that I do know that some of data is truncated when insert and I want to increase varchar length. But do not know, what columns. (Explanation little messy, but probably sql will make sense)
I tried:
select COLUMN_NAME, CHARACTER_MAXIMUM_LENGTH, DATA_TYPE, (SELECT LENGTH(COLUMN_NAME) as maxlen FROM my_database.my_table ORDER BY maxlen DESC LIMIT 1)
from information_schema.columns
where table_schema = 'my_database' AND
table_name = 'my_table'AND DATA_TYPE = 'varchar'
It works, but return the length of the column, but not data inside it. (I.e. id column is called id, I got 2).
If I use JOIN (ON TRUE condition), I got error that COLUMN_NAME is undefined.
Stored procedures does not allow for data return, and function does not allow dynamic sql inside it.
How to tell MySQL (in case of my query) to consider COLUMN_NAME not as a string, but as column name? If this is not, possible in select, how to get columns with maximum data inside them?
Desired result looks like:
column_1 | 25 | varchar | 20
column_2 | 25 | varchar | 7
I am interested only in varchar, as int does not make sense to adjust (and no need to). Columns has different length (varchar(20),varchar(25), etc.).
Update 1: This cannot be done also via loop (statements cannot be executed inside cursor).
I use something like this type of code to generate my view automticaly using table schema. Use can modify according to your need.
$sql = "show tables from DBName where Tables_in_yourtbalename = 'yourtbalename' ";
$result = executeQuery($sql, $conn);
$num = $result->num_rows;
if ($num) {
$sql = "show columns from yourtbalename where Extra != 'auto_increment'";
$result = executeQuery($sql, $conn);
$num2 = $result->num_rows;
while ($r = $result->fetch_assoc()) {
if ($r['Key'] == 'MUL' && ( preg_match("/^int/", $r['Type']) || preg_match("/^smallint/", $r['Type']) || preg_match("/^tinyint/", $r['Type']) || preg_match("/^bigint/", $r['Type']))) {
} else if ($r['Field'] == 'status') {
}
}
Where $r['Field'] is field name and $r['Type'] provides its type. For determining maxlength use
$maxlength="' . substr(str_replace(")", "", $r['Type']), 8, (strlen(str_replace(")", "", $r['Type']))));

Update Same mysql field twice in single query

I am not sure if its possible or not, Just want to know if it is. I have column plan_popular which has default value 0. Lets same i have a list :
Plan Name | plan_popular | amount
===================================
plan A 0 25.00
plan B 1 50.00
plan C 0 90.00
This is how i am doing:
$stmt = "update {CI}plans set plan_popular = 0";
$this->db->query($stmt);
$stmt2 = "update {CI}plans set plan_popular = 1 where plan_id = ?";
$this->db->query( $stmt2, array($plan_id) );
Now i have set the plan C to make. Now i want to reset it and want to make popular plan C to 1. What i am doing is running two queries, One i reset and make the plan_popular 0 and the second is get the update the plan C to 1 with there id. Is it possible in single query?
You can use an expression to determine the value to assign:
UPDATE {CI}plans
SET plan_popular = IF(plan_id = ?, 1, 0);
try this,
UPDATE {CI}plans
SET `plan_popular` = CASE `Plan Name`
WHEN 'plan C' THEN 1
ELSE 0
END
WHERE `Plan Name` IN((select `Plan Name` from {CI}plans where plan_popular=1 ) , 'plan C');
Updates can be expensive, what with manipulating locks, triggers and constraints firing, etc. In general, you want to avoid updating a field to the same value it already has. In English, if plan_id = variable and plan_popular is 0 then set it to 1 but if plan_id is any other value and plan_popular is 1 then set it to 0.
UPDATE {CI}Plans
SET plan_popular = if( plan_id = ?, 1, 0 )
where (plan_id = ? and plan_popular = 0)
or (plan_id <> ? and plan_popular = 1);
The where clause lets through only those rows that will actually be changed by the update. If this is a largish table, that can make quite a difference in response time. Logic is much less expensive than any actual operation that can performed in the database.