How to display zero values in mysql query? - mysql

This code make an operation on a and b and check if result is equal to c.
If yes, just print this row. My question is how to change this code to display
rows when result (a / b) = 0.
SELECT id, a, b, operation, c
FROM expressions
where
case
when operation LIKE '+' AND (a + b = c) then c
when operation LIKE '-' AND (a - b = c) then c
when operation like '/' AND (a / b = c) then c
when operation like '*' AND (a * b = c) then c
ELSE FALSE END;
Output:
id a b operation c
1 2 3 + 5
4 4 7 * 28
11 0 1 / 0
14 239 0 * 0
15 18 18 - 0
1, 2 rows are ok and printed. 3, 4, 5 rows should be printed but they are not!
When a / b = 0 then second condition in sql query is false - row is not printed, e.g. 0 / 1 = 0. It is 0 and should be printed. In contrart to 1 / 0 which shouldn`t be printed.
My solution is to cast (a / b = c) to unsigned but it is not working?

You shouldn't mix types like boolean and int because implicit conversion occurs.
Use explicit value instead of TRUE/FALSE (0 is treated as FALSE).
SELECT id, a, b, operation, c
FROM expressions
where
case
when operation LIKE '+' AND (a + b = c) then 1
when operation LIKE '-' AND (a - b = c) then 1
when operation like '/' AND (a / b = c) then 1
when operation like '*' AND (a * b = c) then 1
ELSE 0 END = 1;
alternatively:
SELECT id, a, b, operation, c
FROM expressions
where
case
when operation LIKE '+' AND (a + b = c) then TRUE
when operation LIKE '-' AND (a - b = c) then TRUE
when operation like '/' AND (a / b = c) then TRUE
when operation like '*' AND (a * b = c) then TRUE
ELSE FALSE END;

As already pointed out, the issue is that 0 is treated as false.
I would simplify the logic to:
SELECT id, a, b, operation, c
FROM expressions
WHERE (operation LIKE '+' AND (a + b = c) ) OR
(operation LIKE '-' AND (a - b = c) ) OR
(operation LIKE '/' AND (a / b = c) ) OR
(operation LIKE '*' AND (a * b = c) );
I don't think the CASE makes the code more understandable.
If you are concerned about divide-by-zero, then use nullif():
(operation LIKE '/' AND (a / nullif(b, 0) = c) ) OR

Related

SQLAlchemy custom formula in sum()

I have a table with columns: a, b, x_1, x_2, x_3, x_4, x_5, y_1, y_2, y_3, y_4, y_5 and need to apply a formula such as: a * (x_i * (1 + (b / (1 - b)) ) + (y_i - x_i)) where i = {1,2,3,4,5}.
My problem is that I need to sum() the results of this formula partitioned w.r.t two the other columns a, b. So the select query will be like:
select(
col_1,
col_2,
func.sum(
a * (x_1 * (1 + (c / (1 - c)) ) + (y_1 - x_1))
).over(partition_by=[col_1, col_2]).label("sum1"),
func.sum(
a * (x_2 * (1 + (c / (1 - c)) ) + (y_2 - x_2))
).over(partition_by=[col_1, col_2]).label("sum2"),
...
func.sum(
a * (x_5 * (1 + (c / (1 - c)) ) + (y_5 - x_5))
).over(partition_by=[col_1, col_2]).label("sum5")
)
As you can see it is cumbersome to maintain and keep repeating the formula is error prone.
Is there a way to wrap this formula so that I can simply refer to formula like below or some way of abstracting it?
select(
col_1,
col_2,
func.sum(my_custom_formula(a, b, x_1, y_1)).over(partition_by=[col_1, col_2]).label("sum1"),
func.sum(my_custom_formula(a, b, x_2, y_2)).over(partition_by=[col_1, col_2]).label("sum2"),
...
func.sum(my_custom_formula(a, b, x_5, y_5)).over(partition_by=[col_1, col_2]).label("sum5")
)
You can hide even more of the implementation detail if you want. The below should give you directional idea:
def get_expression(T: MyTable, pos: int, c):
xn = getattr(T, f"x_{pos}")
yn = getattr(T, f"y_{pos}")
_expr = T.a * (xn * (1 + (c / (1 - c)) ) + (yn - xn))
expr = func.sum(_expr).over(partition_by=[T.col_1, T.col_2]).label(f"sum{pos}")
return expr
q = select(
T.col_1,
T.col_2,
get_expression(T, 1, c),
get_expression(T, 2, c),
get_expression(T, 3, c),
get_expression(T, 4, c),
get_expression(T, 5, c),
)

SQL: can't understand CASE syntax [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 6 years ago.
Improve this question
I'm trying to solve a Hackerrank problem of detecting the triangle type for which I have the following code:
SELECT A,B,C FROM TRIANGLES
CASE
WHEN (A >= B + C) OR (B >= A + C) OR (C >= A + B) THEN "Not A Triangle"
WHEN A = B AND B = C THEN "Equilateral"
WHEN (A = B AND B = C) OR (B = C AND C = A) OR (C = A AND A = B) THEN "Isosceles"
ELSE "Scalene"
END;
But it does not work:
ERROR 1064 (42000) at line 1: 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 'CASE
WHEN (A >= B + C) OR (B >= A + C) OR (C >= A + B) THEN "Not A Trian' at line 2
I suppose you want your output like this:
A B C TYPE
6 2 3 Not a Triangle
3 3 3 Equilater
and so on...
Try this:
SELECT A,B,C,
CASE
WHEN (A >= B + C) OR (B >= A + C) OR (C >= A + B) THEN "Not A Triangle"
WHEN A = B AND B = C THEN "Equilateral"
WHEN (A = B AND B = C) OR (B = C AND C = A) OR (C = A AND A = B) THEN "Isosceles"
ELSE "Scalene"
END AS type
FROM TRIANGLES
Not sure what you intended to do, but this should work :
SELECT A,B,C ,
CASE
WHEN (A >= B + C) OR (B >= A + C) OR (C >= A + B) THEN 'Not A Triangle'
WHEN A = B AND B = C THEN 'Equilateral'
WHEN (A = B AND B = C) OR (B = C AND C = A) OR (C = A AND A = B) THEN 'Isosceles'
ELSE 'Scalene'
END
FROM TRIANGLES
You had two mistakes, first, strings need to be wrapped with single quotes, double quotes are for column names. Second, Syntax is:
SELECT <columns>
FROM <Table>
WHERE <Filters>

MIPS Programming instruction count issue

I wrote this mips code to find the gcf but I am confused on getting the number of instructions executed for this code. I need to find a linear function as a function of number of times the remainder must be calculated before an answer. i tried running this code using Single step with Qtspim but not sure on how to proceed.
gcf:
addiu $sp,$sp,-4 # adjust the stack for an item
sw $ra,0($sp) # save return address
rem $t4,$a0,$a1 # r = a % b
beq $t4,$zero,L1 # if(r==0) go to L1
add $a0,$zero,$a1 # a = b
add $a1,$zero,$t4 # b = r
jr gcf
L1:
add $v0,$zero,$a1 # return b
addiu $sp,$sp,4 # pop 2 items
jr $ra # return to caller
There is absolutely nothing new to show here, the algorithm you just implemented is the Euclidean algorithm and it is well known in the literature1.
I will nonetheless write an informal analysis here as link only questions are evil.
First lets rewrite the code in an high level formulation:
unsigned int gcd(unsigned int a, unsigned int b)
{
if (a % b == 0)
return b;
return gcd(b, a % b);
}
The choice of unsigned int vs int was dicated by the MIPS ISA that makes rem undefined for negative operands.
Out goal is to find a function T(a, b) that gives the number of step the algorithm requires to compute the GDC of a and b.
Since a direct approach leads to nothing, we try by inverting the problem.
What pairs (a, b) makes T(a, b) = 1, in other words what pairs make gcd(a, b) terminates in one step?
We clearly must have that a % b = 0, which means that a must be a multiple of b.
There are actually an (countable) infinite number of pairs, we can limit our selves to pairs with the smallest, a and b2.
To recap, to have T(a, b) = 1 we need a = nb and we pick the pair (a, b) = (1, 1).
Now, given a pair (c, d) that requires N steps, how do we find a new pair (a, b) such that T(a, b) = T(c, d) + 1?
Since gcd(a, b) must take one step further then gcd(c, d) and since starting from gcd(a, b) the next step is gcd(b, a % b) we must have:
c = b => b = c
d = a % b => d = a % c => a = c + d
The step d = a % c => a = c + d comes from the minimality of a, we need the smallest a that when divided by c gives d, so we can take a = c + d since (c + d) % c = c % c d % c = 0 + d = d.
For d % c = d to be true we need that d < c.
Our base pair was (1, 1) which doesn't satisfy this hypothesis, luckily we can take (2, 1) as the base pair (convince your self that T(2, 1) = 1).
Then we have:
gcd(3, 2) = gcd(2, 1) = 1
T(3, 2) = 1 + T(2, 1) = 1 + 1 = 2
gcd(5, 3) = gcd(3, 2) = 1
T(5, 3) = 1 + T(3, 2) = 1 + 2 = 3
gcd(8, 5) = gcd(5, 3) = 1
T(8, 5) = 1 + T(5, 3) = 1 + 3 = 4
...
If we look at the pair (2, 1), (3, 2), (5, 3), (8, 5), ... we see that the n-th pair (starting from 1) is made by the number (Fn+1, Fn).
Where Fn is the n-th Fibonacci number.
We than have:
T(Fn+1, Fn) = n
Regarding Fibonacci number we know that Fn ∝ φn.
We are now going to use all the trickery of asymptotic analysis, particularly in the limit of the big-O notation considering φn or φn + 1 is the same.
Also we won't use the big-O symbol explicitly, we rather assume that each equality is true in the limit. This is an abuse, but makes the analysis more compact.
We can assume without loss of generality that N is an upper bound for both number in the pair and that it is proportional to φn.
We have N ∝ φn that gives logφ N = n, this ca be rewritten as log(N)/log(φ) = n (where logs are in base 10 and log(φ) can be taken to be 1/5).
Thus we finally have 5logN = n or written in reverse order
n = 5 logN
Where n is the number of step taken by gcd(a, b) where 0 < b < a < N.
We can further show that if a = ng and b = mg with n, m coprimes, than T(a, b) = T(n, m) thus the restriction of taking the minimal pairs is not bounding.
1 In the eventuality that you rediscovered such algorithm, I strongly advice against continue with reading this answer. You surely have a sharp mind that would benefit the most from a challenge than from an answer.
2 We'll later see that this won't give rise to a loss of generality.

How to writer the condition A or B is zero , but not both is zero in MYSQL?

What is the correct syntax for the following SQL statement ?
SELECT * FROM TABLE WHERE (A = 0 AND B != 0) OR (A!=0 AND B=0)
Thanks
Updated: How about negative case? I would like to check if A or B is non-zero , but not both is non-zero, Thanks
SELECT OperateProductId FROM DPS_UserLoginStatus Where OperateProductId <> 0 XOR OperateIssueId <> 0
You're looking for the XOR logical operator:
SELECT * FROM TABLE WHERE A = 0 XOR B = 0
In terms of other operators, a XOR b (commonly a ^ b when used bitwise rather than logical), is equivalent to (a and !b) or (b and !a). It's also equivalent to: (a or b) and (!a or !b). In English, it's exactly what you're looking for: a xor b is true if and only if either a or b is true but both are not true.

Mysql Precedence Logic

Any explanation to the following queries :
Select x FROM y WHERE a = 1 OR a = 2 AND (b = 1 OR b = 2)
why it doesn't return the correct info while this return the correct info :
Select x FROM y WHERE (a = 1 OR a = 2) AND (b = 1 OR b = 2)
Am i missing something here ?
X Y (X OR Y) X OR Y
1 0 1 1
0 1 1 1
1 1 1 1
0 0 0 0
I know in term of precedence the () have priority , but why should i add them the the first part of the query ?
Correct me if I'm wrong
Thank you
AND has a higher precedence than OR so your first query is equivalent to this:
Select x FROM y WHERE a = 1 OR a = 3 OR (a = 2 AND (b = 1 OR b = 2))
Which is not equivalent to
Select x FROM y WHERE (a = 1 OR a = 2 OR a = 3) AND (b = 1 OR b = 2)
I guess you forgot the a = 3 part in your first query.
Operator precedence in MySQL
Because ambiguity is an undesirable trait?
Also, the optimizer will re-order your WHERE Conditions if it thinks it will perform better. Your ambiguity will, therefore, cause different results depending on how/what it evaluates first.
Always be explicit with your intentions.
Using parentheses in your WHERE clause does not just affect precedence but also groups predicates together. In your example the difference in results is more a matter of grouping rather than precedence.
You could think of this: (pN = predicate expression)
WHERE a = 1 OR a = 2 AND (b = 1 OR b = 2)
as:
WHERE p1 OR p2 AND p3
And this:
WHERE (a = 1 OR a = 2 OR a = 3) AND (b = 1 OR b = 2)
as:
WHERE p1 AND p2
and so it becomes clear that the results could be quite different.