Using Sum inside a Case statement in MySQL - mysql

I am having problem in MySQL adding three values, this should be simple right?
I have code that selects values from a column based upon the value of a second column, I use a case statement like this:
Select
Max(Case
When Table1.costcode Like '%Costcode1%'
Then Table1.costs
Else Null End) As 'Costcode1',
Max(Case
When Table1.costcode Like '%Costcode2%'
Then Table1.costs
Else Null End) As 'Costcode2',
Max(Case
When Table1.costcode Like '%Costcode3%'
Then Table1.costs
Else Null End) As 'Costcode3',
(Case
When Table1.costcode In ('%Costcode1%','%Costcode2%','%Costcode3%')
Then Sum(Table1.costs)
Else Null End) As 'Total Cost',
From Table1
the first three Case statements work fine and all return values (these are held in the database as negative numbers e.g. -13624.00), however the Total Cost Case just returns Null...
The column Table1.costcode includes many other codes as well so I can't just sum all of the values without picking them out first.
It must be simple to sum these values, but obviously I'm missing something… Help, please :-)
Thanks

Try this -
SUM(Case Table1.costcode
When LIKE ('%Costcode1%') Then Table1.costs
When LIKE ('%Costcode2%') Then Table1.costs
When LIKE ('%Costcode3%') Then Table1.costs
Then Table1.costs
Else 0.00 End) As 'Total Cost'

Related

MYSQL - Rows to columns transpose [duplicate]

This question already has answers here:
MySQL - Rows to Columns
(13 answers)
Closed 1 year ago.
I've looked at similar posts (specifically MySQL - Rows to Columns), and from that wrote the MYSQL statement below in an effort to correctly transpose rows to columns. The transposition works for the most part, but only one IT.TaxStatus is selected and given for each row (that is for each IT.ClientCode), and I cannot for the life of me figure out why.
SELECT IT.ClientCode,
CASE WHEN IT.TaxYear='2021' THEN IT.TaxStatus ELSE NULL END AS '2021',
CASE WHEN IT.TaxYear='2020' THEN IT.TaxStatus ELSE NULL END AS '2020',
CASE WHEN IT.TaxYear='2019' THEN IT.TaxStatus ELSE NULL END AS '2019',
CASE WHEN IT.TaxYear='2018' THEN IT.TaxStatus ELSE NULL END AS '2018'
FROM IT GROUP BY IT.ClientCode
Order by IT.ClientCode;
My original table:
Original table
Expected result:
Expected Result
Do anyone have an explanation why only one IT.TaxStatus per IT.ClientCode would be given in the final recordset, and not all the years?
Thank you for your assistance!
Regards
Wessel
You need to add an aggregation function
SELECT IT.ClientCode,
MAX(CASE WHEN IT.TaxYear='2021' THEN IT.TaxStatus ELSE NULL END) AS '2021',
MAX(CASE WHEN IT.TaxYear='2020' THEN IT.TaxStatus ELSE NULL END) AS '2020',
MAX(CASE WHEN IT.TaxYear='2019' THEN IT.TaxStatus ELSE NULL END) AS '2019',
MAX(CASE WHEN IT.TaxYear='2018' THEN IT.TaxStatus ELSE NULL END) AS '2018'
FROM IT
GROUP BY IT.ClientCode
Order by IT.ClientCode;

Use a generated column in MariaDB 5.5.52

I have a valid sql statement that looks like this:
SELECT SUM(CASE WHEN faell_art='monatlich' THEN betrag*12 END) + SUM(CASE WHEN faell_art='vierteljährlich' THEN betrag*4 END) + SUM(CASE WHEN faell_art='halbjährlich' THEN betrag*2 END) + SUM(CASE WHEN faell_art='jährlich' THEN betrag END) as total FROM banking
Now I want to create a generated column which does exactly the same. I tried this statement:
ALTER TABLE `banking` ADD `test` DECIMAL(10,2) AS (SUM(CASE WHEN faell_art='monatlich' THEN betrag*12 END) + SUM(CASE WHEN faell_art='vierteljährlich' THEN betrag*4 END) + SUM(CASE WHEN faell_art='halbjährlich' THEN betrag*2 END) + SUM(CASE WHEN faell_art='jährlich' THEN betrag END)) AFTER `kommentar`;
However it doesn´t work ("#1901 - Function or expression is not allowed for column 'test'").
Any help? Thx :-)
There is a limitation:
subqueries or anything that depends on data outside the row are not
allowed (these are not deterministic because the underlying data can
change).
All aggregate functions (SUM,...) operate with other records in the table.
Virtual (Computed) Columns.
So, that generated column cannot be created. Or, you could create a view.

COUNT(DISTINCT(CASE WHEN IN ('A','B')

Hi Everyone wondered if anyone could help with the below:
SELECT
HOST_ORDER_NO,
EARLIEST_PICK_DATE,
PRODUCT_NO,
PRODUCT_NUM_PARTS,
PRODUCT_WHS_LOCATION,
COUNT(DISTINCT(CASE
WHEN LEFT(PRODUCT_WHS_LOCATION,1) IN ('A','B','C','K','M','N') THEN 'BULK'
WHEN LEFT(PRODUCT_WHS_LOCATION,1) IN ('D','E','F') THEN 'TEN'
WHEN LEFT(PRODUCT_WHS_LOCATION,1) IN ('G','H','I','J','L') THEN 'TENSMALL'
ELSE 'SIP' END) AS 'ZONE',
MAX(COLLATION_INDICATOR),
COLLATION_GROUP_ID,
CASE WHEN COUNT(HOST_ORDER_NO)=1 THEN 'SingleOrder' ELSE 'MultiItem' END AS 'OrderType',
COUNT(*) AS 'ItemsInOrder',
YEARWEEK
FROM wk19
WHERE YearWeek = '201717'
GROUP BY HOST_ORDER_NO
HAVING OrderType = 'MultiItem'
ORDER BY HOST_ORDER_NO, COLLATION_GROUP_ID, MAX(COLLATION_INDICATOR);
My error is in the case statment I want to be able to see how many different areas the orders are coming from with in the warehouse. The rest of the statement works fine, but if I need to breck it down more I can do.
Your case expression is just missing parentheses. No paren is needed after distinct, so:
COUNT(DISTINCT CASE WHEN LEFT(PRODUCT_WHS_LOCATION,1) IN ('A','B','C','K','M','N') THEN 'BULK'
WHEN LEFT(PRODUCT_WHS_LOCATION,1) IN ('D','E','F') THEN 'TEN'
WHEN LEFT(PRODUCT_WHS_LOCATION,1) IN ('G','H','I','J','L') THEN 'TENSMALL'
ELSE 'SIP'
END) AS ZONE,
A word of advice: Only use single quotes for strings and dates. Don't use them for column aliases.

How to group same kind of values into common one and group by that

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

complex math routines in mysql

I have a table in Mysql that has field code with a value = 'A' that represents the type of sale of a part. The sale price is displayed as Price. There is a Quantity field that I need to multiply by the Price. The query sum(quantity*price) where code='A' gives me what I want. I also have a code = 'T' that represents the tax of the sum of the transactions. I can get that easy enough by sum(price) where code='T'. I need to subtract the value of the 'T' (tax) value from the sum(quantity*price).
I can do this by looping through two separate queryies but I would like to combine into one query.
You just want conditional aggregation:
select (sum(case when value = 'A' then quantity * price else 0 end) -
sum(case when value = 'T' then price else 0 end)
) as netprice