MySQL Update CASE updates field with "0" - mysql

I have a problem by updating my SQL-Table with the CASE statement.
SELECT number,amount,minimuminventory FROM artikel WHERE number=17;
+--------+--------+------------------+
| number | amount | minimuminventory |
+--------+--------+------------------+
| 17 | 10 | 0 |
+--------+--------+------------------+
I have an amount of 10 but when I update my table:
UPDATE artikel
SET amount = CASE WHEN amount - minimuminventory - 2 < 0
THEN amount=amount-2
ELSE amount=99
END
WHERE artnr=17;
Query OK, 1 rows affected (0,01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql updates my table an sets amount to 0
SELECT number,amount,minimuminventory FROM artikel WHERE number=17;
+--------+--------+------------------+
| number | amount | minimuminventory |
+--------+--------+------------------+
| 17 | 0 | 0 |
+--------+--------+------------------+
Do you you see the problem?

amount = CASE WHEN amount - minimuminventory - 2 < 0 THEN amount=amount-2 ELSE amount=99 END
The value from the CASE statement is the intended value for the amount column, but you're doing amount=x again inside the THEN and ELSE parts of it. Change it to this:
amount = CASE WHEN amount - minimuminventory - 2 < 0 THEN amount-2 ELSE 99 END

Do you you see the problem?
In your statement:
UPDATE artikel
SET amount = CASE WHEN amount - minimuminventory - 2 < 0
THEN amount=amount-2
ELSE amount=99
END
WHERE artnr=17;
The comparison is interpreted as boolean but not as assignment.
SET amount = (amount=amount-2) -- comparison as if amount is equal to (17=17-2)
SET amount = (amount=99) -- comparison as if amount is equal to (17=99)
SET amount = false -- i.e. 0, because 17 != 15 or 17 != 99
That resulted a value of 0 in amount column.
Change your update statement as below:
UPDATE artikel
SET amount = CASE WHEN amount - minimuminventory - 2 < 0
THEN amount-2
ELSE 99
END
WHERE artnr=17;

Related

Creating a column being the multiple of others

I need some help. I have 2 colluns from mysql query result: 1 with text, and another with decimal values. Like that:
select desc, value from table a
|5,50 % | 2984.59 |
|Subs | 10951.70 |
|Isent | 3973.17 |
|13,30 % | 560.26 |
From the rows that have the %, I want to multiply the values and create a third result column, rounding up to two decimal places. See above
2984,59 * 0,055 = 164,15245
560,26 * 0,133 = 74,514
I need make the sql query that show something like above.
+-------+-----------+-----------+
|5,50 % | 2984,59 | 164,16 |
|Subs | 10951,70 | 0 or NULL |
|Isent | 3973,17 | 0 or NULL |
|13,30% | 560,26 | 74,52 |
+-------+-----------+-----------+
How i can do it?
Thanks so much for help
It would be better to have floaring numbers in the first place, converting costs time
You have commas in your procentage, but mysql needs dots there
If value isn't always a number, you can use the mysql way to add a 0 0 to it, that remioves all non numerical characters
SELECT `desc`, `value`, (REPLACE(`desc`,',','.') + 0) * `value` / 100 FROM val
desc
value
(REPLACE(`desc`,',','.') + 0) * `value` / 100
5,50 %
2985
164.175
Subs
10952
0
Isent
3973
0
13,30 %
560
74.48
fiddle
SELECT `desc`, `value`, CEIL((REPLACE(`desc`,',','.') + 0) * `value`) / 100 FROM val
desc
value
CEIL((REPLACE(`desc`,',','.') + 0) * `value`) / 100
5,50 %
2985
164.18
Subs
10952
0
Isent
3973
0
13,30 %
560
74.48
fiddle

MySQL calculating query

I have this table, only two columns, each record stores an interest rate for a given month:
id rate
===========
199502 3.63
199503 2.60
199504 4.26
199505 4.25
... ...
201704 0.79
201705 0.93
201706 0.81
201707 0.80
201708 0.14
Based on this rates, I need to create another table of accumulated rates which similar structure, whose data is calculated as function of a YYYYMM (month/year) parameter, this way (this formula is legally mandatory):
The month given as parameter has always rate of 0 (zero)
The month immediately previous has always a rate of 1 (one)
The previous months' rates will be (one) plus the sum of rates of months between that given month and the month given as parameter.
I'll clarify this rules with this example, given parameter 201708:
SOURCE CALCULATED
id rate id rate
=========== =============
199502 3.63 199502 360.97 (1 + sum(rate(199503) to rate(201707)))
199503 2.60 199503 358.37 (1 + sum(rate(199504) to rate(201707)))
199504 4.26 199504 354.11 (1 + sum(rate(199505) to rate(201707)))
199505 4.25 199505 349.86 (1 + sum(rate(199506) to rate(201707)))
... ... ... ...
201704 0.79 201704 3.54 (1 + rate(201705) + rate(201706) + rate(201707))
201705 0.93 201705 2.61 (1 + rate(201706) + rate(201707))
201706 0.81 201706 1.80 (1 + rate(201707))
201707 0.80 201707 1.00 (per definition)
201708 0.14 201708 0.00 (per definition)
Now I've already implemented a VB.NET function that reads the source table and generates the calculated table, but this is done in runtime at each client machine:
Public Function AccumRates(targetDate As Date) As DataTable
Dim dtTarget = Rates.Clone
Dim targetId = targetDate.ToString("yyyyMM")
Dim targetIdAnt = targetDate.AddMonths(-1).ToString("yyyyMM")
For Each dr In Rates.Select("id<=" & targetId & " and id>199412")
If dr("id") = targetId Then
dtTarget.Rows.Add(dr("id"), 0)
ElseIf dr("id") = targetIdAnt Then
dtTarget.Rows.Add(dr("id"), 1)
Else
Dim intermediates =
Rates.Select("id>" & dr("id") & " and id<" & targetId).Select(
Function(ldr) New With {
.id = ldr.Field(Of Integer)("id"),
.rate = ldr.Field(Of Decimal)("rate")}
).ToArray
dtTarget.Rows.Add(
dr("id"),
1 + intermediates.Sum(
Function(i) i.rate))
End If
Next
Return dtTarget
End Function
My question is how can I put this as a query in my database so it can be used dynamically by other queries which would use these accumulated rates to update debts to any given date.
Thank you very much!
EDIT
I managed to make a query that returns the data I want, now I just don't know how to encapsulate it so that it can be called from another query passing any id as argument (here I did it using a SET ... statement):
SET #targetId=201708;
SELECT
id AS id_acum,
COALESCE(1 + (SELECT
SUM(taxa)
FROM
tableSelic AS ts
WHERE
id > id_acum AND id < #targetId
LIMIT 1),
IF(id >= #targetId, 0, 1)) AS acum
FROM
tableSelic
WHERE id>199412;
That's because I'm pretty new to MySQL, I'm used to MS-Access where parametrized queries are very straightfoward to create.
For example:
DROP TABLE IF EXISTS my_table;
CREATE TABLE my_table
(id INT NOT NULL PRIMARY KEY
,rate DECIMAL(5,2) NOT NULL
);
INSERT INTO my_table VALUES
(201704,0.79),
(201705,0.93),
(201706,0.81),
(201707,0.80),
(201708,0.14);
SELECT *
, CASE WHEN #flag IS NULL THEN #i:=1 ELSE #i:=#i+rate END i
, #flag:=1 flag
FROM my_table
, (SELECT #flag:=null,#i:=0) vars
ORDER
BY id DESC;
+--------+------+-------------+-------+------+------+
| id | rate | #flag:=null | #i:=0 | i | flag |
+--------+------+-------------+-------+------+------+
| 201708 | 0.14 | NULL | 0 | 1 | 1 |
| 201707 | 0.80 | NULL | 0 | 1.80 | 1 |
| 201706 | 0.81 | NULL | 0 | 2.61 | 1 |
| 201705 | 0.93 | NULL | 0 | 3.54 | 1 |
| 201704 | 0.79 | NULL | 0 | 4.33 | 1 |
+--------+------+-------------+-------+------+------+
5 rows in set (0.00 sec)
Ok, I made it with a function:
CREATE FUNCTION `AccumulatedRates`(start_id integer, target_id integer) RETURNS decimal(6,2)
BEGIN
DECLARE select_var decimal(6,2);
SET select_var = (
SELECT COALESCE(1 + (
SELECT SUM(rate)
FROM tableRates
WHERE id > start_id AND id < target_id LIMIT 1
), IF(id >= unto, 0, 1)) AS acum
FROM tableRates
WHERE id=start_id);
RETURN select_var;
END
And them a simple query:
SELECT *, AccumulatedRates(id,#present_id) as acum FROM tableRates;
where #present_id is passed as parameter.
Thanks to all, anyway!

I want to OR a column with a number and store it back in same columns based on multiple conditions in Mysql

I have the following table called DETAILS.
if Flag is 1 -->00000001 //(1st LSB is set here)
if flag is 2 -->00000010 //(2nd LSB is set here)
if flag is 3 -->00000011 //(1st,2nd LSB's are set here)
if flag is 5 -->00000101 //(1st,3rd LSB's are set here)
Sample data:
ID NAME FLAG(int) IS_LAST
--------------------------------------
1 sports 5 (0000 0101) 0 //1st,3rd LSB's are set
2 News 11 (0000 1011) 0 //1,2,4 MSB's are set
3 Weather 24 (0001 1000) 1 //4,5 MSB's are set
4 IPL 32 (0010 0000) 0 //6th MSB is set
If 2nd LSB or 6th LSB of FLAG column or IS_LAST=1, then I want to OR the FLAG with 64 (0100 0000) and store the result back in to same FLAG column using UPDATE query.
I want the output like this:
ID NAME FLAG(int) IS_LAST
-------------------------------------------------
1 sports 5 (0000 0101)(Not updated) 0
2 News 75 (0100 1011)(updated) 0
3 Weather 88 (0101 1000)(updated) 1
4 IPL 96 (0110 0000)(updated) 0
My SQL has a bitwise or operator - |, so this is just a straightforward update statement:
UPDATE details
SET flag = flag | 64
WHERE (flag | 2 > 0) OR
(flag | 32 > 0) OR
(is_last = 1)

Is there a way to merge boolean value fields in MySQL?

I have a table that contains several fields with Boolean values.
I need 3 of the fields to be merged into one only if all 3 of them are true.
I was thinking about a JOIN, but it looks like it cannot do what I need.
------------------------------------------------------------
| Email address| permission1 | permission2 | permission3
------------------------------------------------------------
| test#test.com| 1 | 0 | 1
------------------------------------------------------------
| test2#test.com| 1 | 1 | 1
------------------------------------------------------------
I would expect a result, perhaps in a new table to look like this:
--------------------------------
| Email address| permissionMerge
--------------------------------
| test#test.com| 0 |
--------------------------------
| test2#test.com| 1 |
--------------------------------
You could use CASE syntax
SELECT `email address`,
CASE WHEN `permission1` = 1
AND `permission2` = 1
AND `permission3` = 1
THEN 1
ELSE 0 END AS 'permissionMerge'
FROM `Table`
You could also do it that way:
SELECT `email address`,
CASE WHEN SUM(`permission1`,`permission2`,`permission3`) = 3
THEN 1
ELSE 0 END AS 'permissionMerge'
FROM `Table`
GROUP BY `email address`
Select `Email adderss`,(permission1 and permission2 and permission3) as permissionMerge from table
Depending on the quality of data, you could get away with something as simple as:
SELECT address,
CASE SUM(permission1, permission2, permission3)
WHEN 3 THEN 1
ELSE 0
END AS permissionMerge
FROM undisclosed_table
... or you'll need something more robust:
SELECT address,
CASE
WHEN permission1 IS TRUE AND permission2 IS TRUE AND permission3 IS TRUE THEN 1
ELSE 0
END AS permissionMerge
FROM undisclosed_table
You can generate a new table with:
CREATE TABLE table_with_duplicate_data
SELECT address,
CASE
WHEN permission1 IS TRUE AND permission2 IS TRUE AND permission3 IS TRUE THEN 1
ELSE 0
END AS permissionMerge
FROM undisclosed_table
... thought I'd advise against it: it'll just waste storage and you need to keep data up-to-date. If it's too much typing, you can create a view or (since MySQL/5.7.5) a generated column.

Output 0 if calculations is negative, else do calculations

=MAX(IF
(Table_ExternalData_2[name]=$A$2,Table_ExternalData_2[date_booked])) - MIN(IF(Table_ExternalData_2[name]=$A$2,Table_ExternalData_2[date_booked]))
Sorry if this is such an easy question but I can't figure it out. What I'm trying to do is, if the result is negative, the output will be zero, if not then minus the columns.
| Col1 | Col2 |
| 42 | 233 |
If i minus 42 - 233, I will get -191.
How can I tell mysql that if the result is a negative, output 0 and if not then minus the two columns?
SELECT IF(Col1-Col2 =< 0, 0, Col1-Col2)
Is as simple as this?
You can use CASE WHEN (condition) THEN (true) ELSE (false) END
SELECT CASE WHEN (Col1-Col2) =< 0 THEN 0 ELSE (Col1-Col2) END AS Num1 FROM ....