mysql - difference between two integer column doesn't works as expected - mysql

I'm run this query:
SELECT id,like - dislike as result
FROM mytable
Where the column like and dislike are unsigned integer. If the column dislike is greater than like mysql return number like 18446744073709551596, so seem that mysql treat this like unsigned and can't return negative number but continue the computation from a sort of MAX_UNSIGNED_INT. How can I have the correct result

Try casting the two values (or maybe only on of them)
SELECT id, convert(like, SIGNED ) - convert(dislike, SIGNED ) as result
FROM mytable
or only the result
SELECT id, convert(like - dislike, SIGNED ) as result
FROM mytable
In the first way you can get type overflow! The Second way is better, but I'm not sure it works with mysql.

You could try casting them as Int:
SELECT id, CAST(like AS INT) - CAST(dislike AS INT) as result FROM mytable

Related

Min function returning max valu and Max function returning min value

I have a table "abcd" with column name as "avg" and values "100" and "83".
When I try
select max(avg) from abcd -- Returns 83
select min(avg) from abcd -- Returns 100
seems quite weird to me. I have never imagined that I will be posting something like this in SO. It might be a minor thing to look but it's kicking my day out to solve it.
Am using MySQL and phpMyAdmin
Sounds like a string. A simple solution is to turn it to a number:
select max(avg + 0)
This uses "silent conversion", so it will not raise an error if the value is not numeric.
A better solution might be to turn it into an actual number in the data:
alter table t modify column avg int;
(The values appear to be integers.)
change the datatype of your column avg
if you using varchar its give wrong output on number function
using below query alter the column
ALTER TABLE `abcd` CHANGE `avg` `avg` INT(11) NOT NULL;
OR try this
SELECT max( cast(avg as unsigned) ) as avg FROM `abcd`
SELECT min( cast(avg as unsigned) ) as avg FROM `abcd`

select avg(),min(),max(),toatl(),count() of selected result

I am trying to calculate average,min,max,total,count but i am getting wrong result.
SELECT t0.brandID, t0.brandName, t0.cdt, t0.udt, t0.brandstatus, t0.AddedBy ,
AVG(t0.brandID) AS brandID_AVERAGE,
min(t0.brandid) as branid_min,
MAX(t0.brandid) as brandid_max,
COUNT(t0.brandid) as brandid_count
FROM brands t0
Where t0. brandID=null OR t0. brandName='khasim'
group by t0.brandID,t0.brandName,t0.cdt,t0.udt,t0.brandstatus,t0.AddedBy
select AVG(CAST (brandID AS bigint)) AS brandID_AVERAGE,
min(CAST (brandID AS bigint)) as branid_min,
MAX(CAST (brandID AS bigint)) as brandid_max,
COUNT(CAST (brandID AS bigint)) as brandid_count from
(SELECT t0.brandID, t0.brandName, t0.cdt, t0.udt, t0.brandstatus, t0.AddedBy
FROM brands t0
Where t0. brandID=null OR t0. brandName='budwieser'
group by t0.brandID,t0.brandName,t0.cdt,t0.udt,t0.brandstatus,t0.AddedBy) temptable
i have changed my query to select avg etc for the result of select now
i am getting what i expect, but i want to show all selected columns in
one table how to do.
expected result
result for the above query is
Firstly. From my best knowledge in SQL null is not equal to null. So you need to use is null to check is value equals to null.
Secondly. Could you explain please what is wrong with underlined values?
Your first query where you're returning one row looks correct. Your second screenshot where you get many rows looks like you are using WINDOWING functions (i.e. anything with an OVER clause). This does not aggregate data, it returns all rows and repeats the calculations over the set while returning every row.
Can you include the full query text that is producing the incorrect result?
Also, it could be caused by brandId being an integer type, in which case all calculations on it will use integer-based arithmetic (i.e. no fractions). This is fine if you only expect integer results, but if you need fractions, try using CAST to convert all the occurrences of brandid to decimal types, like this: CAST(brandId as decimal(18, 8)) before doing the AVG and other calculations.

How to simplify a multiple cast MySql select statement?

I am trying to perform a MySql select with many conditions, but want to perform a string comparison on a column that is an integer datatype. Is there a way to do this without having to cast the column to a varchar on every single condition within the where clause?
SELECT COUNT(*)
FROM tablename
WHERE CAST(col1 AS VARCHAR(10)) NOT LIKE '558%'
AND CAST(col1 AS VARCHAR(10)) NOT LIKE '566%'
AND CAST(col1 AS VARCHAR(10)) NOT LIKE '567%'
AND CAST(col1 AS VARCHAR(10)) NOT LIKE '568%'
AND CAST(col1 AS VARCHAR(10)) NOT LIKE '569%'
AND CAST(col1 AS VARCHAR(10)) NOT LIKE '579%';
Before you ask why I'm not doing integer comparison: Instead of casting to a varchar, I could also just use plain integer comparison, but then I still would have to perform a math operation, i.e. col1/100000, for every item in the where clause, which leads to the same problem as to how can I simplify the statement?
You can use subquery:
SELECT COUNT(*)
FROM
(
SELECT CAST(col1 AS VARCHAR(10)) AS col1
FROM tablename
) AS t
WHERE t.col1 NOT LIKE '558%'
...
The direct answer to your question is that casts are implicit in MySQL, so col1 NOT LIKE '556%' is equivalent to what you're doing.
It's always best to avoid using functions that reference column names in the WHERE clause, because that disables the use of indexes and requires every row in the table to be evaluated. I assume that you are aware of that, since you mentioned you would still "have to do a math operation."
If you actually know the scale of the number then a more correct query would be...
WHERE (col1 < 556 * 100000 OR col1 > 556 * 100000)
AND ...
If that's logically correct based on what you are doing, then it's a better solution, because the optimizer will do that math only once, converting those into constants, rather than doing it once per row.
Also note that if you do know the scale of the numbers, then LIKE '556______' is also more logically valid than using % since _ matches exactly one character, where % matches zero or more.

MySQL how to make negative results possible when subtracting unsigned values?

I have three tables joined by left join. Here's the code:
SELECT
(LEAST(`a`.`price, `b`.`price`) - `c`.`price`) AS `diff`
...
ORDER BY `diff` DESC
The problem: c.price is greater than the LEAST, thus the subtraction is negative and throws BIGINT UNSIGNED value is out of range.
How can I make it NOT throw this ridiculous error?
This is result data, I'm not modifying the actual data in the table, so why does it not allow me to do this normally?
I've tried CAST(LEAST(...) AS SIGNED) and casting both columns inside LEAST as signed, neither worked.
Cast as SIGNED each number before LEAST and before substract
SELECT
(LEAST(CAST(`a`.`price` AS SIGNED), CAST(`b`.`price` AS SIGNED)) - CAST(`c`.`price` AS SIGNED)) AS `diff`
...
ORDER BY `diff` DESC
You may want to check the NO_UNSIGNED_SUBTRACTION operator: http://dev.mysql.com/doc/refman/5.0/en/server-sql-mode.html#sqlmode_no_unsigned_subtraction.
There are risks in using it, though: http://datacharmer.blogspot.fi/2006/11/hidden-risks-of-sql-mode.html

Mysql INT with a character

I have a mysql database with a field "order_number" set as an INT on the odd occasion the order number would need to have a trailing r eg 2100r obviously INT will only accept numbers and would sort the number correctly ASC or DESC if I use VARCHAR to overcome this restriction it will correctly accept the trailing r character but will not sort the numbers in numerical order correctly, is there a way INT option can be forced to accept a character?
You need to store your account ids as character strings if any of them contain letters. But you can order them correctly as long as the letters are always suffixes. This works whether or not your AccountID values have leading spaces.
SELECT *
FROM Account
ORDER BY CAST(AccountID as UNSIGNED INTEGER), AccountID
This will order numerically, and then deal with any equal numbers by ordering lexically.
http://sqlfiddle.com/#!2/a16bf/8/0
If you wanted the "r" orders to be shown before their unadorned friends with the same number, you could do this:
SELECT *
FROM Account
ORDER BY CAST(AccountID as UNSIGNED INTEGER), AccountID DESC
you can use CAST function in MySQL but it's a good practice to store order_number as int using typecasting before inserting new data in table.
SELECT CAST(int_col AS CHAR);
SELECT CAST(char_col AS unsigned INTEGER);
No, there is no such option.
You should probably use a VARCHAR column for the order number and a separate column (possibly INT) just for sorting; populate the helper column based on what the order number is when inserting and updating rows.
Try to convert string to number using this way (number_string * 1), e.g. -
SELECT * FROM table ORDER BY column * 1;
No , Not possible. As #Jon said, there is no other options to force an INT field to keep VARCHAR data.