I have a mysql table with columns:
value - integer
type - integer
value only can be positive integer, type can be 0 or 1
I need to sum this value, but the thing is that if type value is 1 i need to subtract this row value from my sum.
Is its possible to make without two queries?
You can try something like this, using if:
sum( if(`type` = 1, -1, 1) * `value` )
Or case:
sum( (case when `type` = 1 then -1 else 1 end) * `value` )
Related
In MySQL Database I have a table ABC that consists of a column 'LastDate'.
LastDate which has datatype as DATETIME. The default value for this 'NULL'
I need to write a query for the table which would
Return '1' in these cases.
1) If DATEDIFF(CURRENT_TIME,LastDate) is >15 or if DATEDIFF(CURRENT_TIME,LastDate) is
NULL(i.e defaultVal).
return '0' if DATEDIFF(CURRENT_TIME,LastDate) is <15.
I tried to write an SQL query for this but was unable to do it. Please help me write this Query. Thanks in advance.
You can be explicit about your logic:
select t.*,
(case when DATEDIFF(CURRENT_TIME, LastDate) > 15 or
LastDate is null
then 1 else 0
end) as flag
from t;
This can be simplified to:
select t.*,
coalesce(DATEDIFF(CURRENT_TIME, LastDate) <= 15, 1) as flag
from t;
I need to make a column that counts the amount of variables which are above 0, and that won't return null if there is any non-null value in it, for each value in an id column.
What I managed to make is using a sum between some boolean operations:
IF 'A' THEN 'B' ELSE 'C' (at least that's what I've got)
select ID, `jul`, `aug`, `set`, `oct`, `nov`, `dec`,
((((not `jul`) or 1) and (`jul` or 0))
+(((not `aug`) or 1) and (`aug` or 0))
+(((not `set`) or 1) and (`set` or 0))
+(((not `out`) or 1) and (`out` or 0))
+(((not `nov`) or 1) and (`nov` or 0))
+(((not `dec`) or 1) and (`dec` or 0))) as sum from table;
It works at first view, but if there is any null value in a line, the sum returns null for each respective id.
What could I do to avoid this problem?
try
SUM( IFNULL(jul,0)+IFNULL(ago,2) ) as sum from table
/*
obs: the SUM is good to sum multiple values
IFNULL returns 0 to the sum if jul is null and 2 for ago if ago is null in the example.
*/
i think it works. :)
You need to use a coalesce or variant to deal with nulls. Null value represents an unknown. You can't add unknowns and get something other than an unknown.
NULL + 1 = NULL
COALESCE(NULL, 0) + 1 = 1
Use isnull(columnname, 0) to turn nulls into 0s. So isnull('jul',0)+isnull('aug',0) etc.
Hi I was looking for a mysql query result like
As you can see there are some values have the kind of values (Ex: BV and BR or C5 and C7) how can I combine then together into one common value lets say B or C and group by that in sql?
I have the following query:
SELECT
type,
sum(case when status ='valid' then 1 else 0 end) valid_jobs,
sum(case when status ='non-valid' then 1 else 0 end) non_valid_jobs,
sum(case when status IS NULL then 1 else 0 end) null_jobs
from
main_table
where
SUBSTRING_INDEX(CAST(CAST(from_unixtime(date_generated) AS DATE) AS CHAR), '-',2) REGEXP '^2016'
group by type
Thanks in advance guys.
Otcome will look like:
Just use an expression that evaluates the value of the type column, and returns the desired result.
What's not clear from the question is the "mapping" from type to the value you want returned in the first column. It looks like we might be looking at just the first character of value in the type column.
SUBSTR(type,1,1)
If the "mapping" is more involved, then we could use a CASE expression. For example:
CASE
WHEN type IN ('BV','BR','BT','ZB') THEN 'B'
WHEN type IN ('C5','C7') THEN 'C'
WHEN ... THEN ...
ELSE type
END
We'd use that as the first expression in the SELECT list (replacing the reference to the type column in the original query), and in the GROUP BY clause.
On an (unrelated) performance note, we'd prefer conditions in the WHERE clause to be on bare columns. That allows MySQL to make use of an (efficient) range scan operation on an appropriate index.
With this condition:
WHERE SUBSTRING_INDEX(CAST(CAST(FROM_UNIXTIME( t.date_generated ) AS DATE) AS CHAR), '-',2)
REGEXP '^2016'
We're forcing MySQL to evaluate the expression on the left side for every row in the table. And the value returned by the expression is compared.
If what we're really trying to do is get date_generated values in 2016, assuming that date_generated is INTEGER type, storing 32-bit unix-style number of seconds since beginning of the era 1970-01-01...
We can do something like this:
WHERE t.date_generated >= UNIX_TIMESTAMP('2016-01-01')
AND t.date_generated < UNIX_TIMESTAMP('2017-01-01')
MySQL will see that as a range operation on the values in te date_generated column. And with that, MySQL can make effective use of an index that has date_generated as a leading column.
Just replace expr with the expression that returns the values you want in the first column:
SELECT expr
, SUM(IF( t.status = 'valid' ,1,0)) AS valid_jobs
, SUM(IF( t.status = 'non-valid' ,1,0)) AS non_valid_jobs
, SUM(IF( t.status IS NULL ,1,0)) AS null_jobs
FROM main_table t
WHERE t.date_generated >= UNIX_TIMESTAMP('2016-01-01')
AND t.date_generated < UNIX_TIMESTAMP('2017-01-01')
GROUP BY expr
EDIT
To guarantee that rows are returned in a particular sequence, add an ORDER BY clause, e.g.
ORDER BY 1
try this,
SELECT
LEFT(type,1) AS type,
sum(case when status ='valid' then 1 else 0 end) valid_jobs,
sum(case when status ='non-valid' then 1 else 0 end) non_valid_jobs,
sum(case when status IS NULL then 1 else 0 end) null_jobs
FROM
main_table
WHERE
SUBSTRING_INDEX(CAST(CAST(from_unixtime(date_generated) AS DATE) AS CHAR), '-',2) REGEXP '^2016'
GROUP BY
type
I have following two queries:
select count * form a where temp>str group by x,y
select count * form a where temp<=str group by x,y
This result in parsing of table twice. Since the table size is 100 of gigs I was thinking if we can reduce this to single query.
select sum(IF(temp>'str',1,0)) as GREATER,
sum(IF(temp<'str',1,0)) as LESSER
from a
group by x,y
This will return a single row with two fields, GREATER and LESSER, which contain the counts of the number of rows which are Greater and Lesser than the string respectively.
IF(temp>'str',1,0)) returns a 1 if greater, else 0. Summing these values will give the total number of rwos which are greater.
IF(temp<'str',1,0)) returns a 1 if lesser, else 0. Summing these values will give the total number of rwos which are lesser.
Try this:
SELECT
SUM(CASE WHEN `temp` > `str` THEN 1 ELSE 0 END) AS `greater`,
SUM(CASE WHEN `temp` < `str` THEN 1 ELSE 0 END) AS `less`
FROM
`a`
GROUP BY
`x`,
`y`
I sum up the rows of two columns in two tables i.e. something like this:
SUM( tableA.age ) + sum( tableB.age) as 'Total Ages'
But in some cases the result of table A is null while result of table B is not. In this case I get as a total result null although it is something like "NULL + 45" which is not null actually. Therefore I thought it would be a good idea to use the if clause of the sql syntax. But it does not work I get an error when trying to do the following:
IF SUM( tableA.age ) IS NULL THEN 0 ELSE SUM( tableA.age ) END IF + IF SUM( tableB.age ) IS NULL THEN 0 ELSE SUM( tableB.age ) END IF
How would I do that in a proper way?
Simply use IFNULL() when you feel the field has NULL value.
SUM(IFNULL(tableA.age,0) )
You can use this MYSQL function.
Instead of the complex (and syntactically incorrect) IF statements, use COALESCE(), which returns its first non-null argument, and specify 0 as its second argument so it defaults to zero when the aggregate SUM() is null
COALESCE(SUM(tableA.age), 0) + COALESCE(SUM(tableB.age), 0)
Use IFNULL(column, 0) to convert the column value to zero:
SUM( IFNULL(tableA.age,0) ) + SUM( IFNULL(tableB.age,0) ) as 'Total Ages'