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

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.

Related

How to use a created column as argument to ORDER BY with CASE clause in MySQL? (#42S22 error)

I need some help over here.
I'm working with some reports generation using MySQL. One of the columns I created was called TOTALSUM and it was created by an operation using a CASE clause. When I try to use an ORDER BY, it accepts this TOTALSUM, but if I include this inside a IF os CASE clause, it doesn't accept anymore.
SUM(CASE WHEN COL1 = 01 THEN COL2 ELSE 0 END) + SUM(CASE WHEN COL1 = 03 THEN -COL2 ELSE 0 END) AS TOTALSUM,
If I do something like this, it works:
ORDER BY TOTALSUM
But if I do something like that, it doesn't work, giving the following error: #42S22Reference 'TOTALSUM' not supported (reference to group function)
ORDER BY IF(:INPUTVALUE = "X",TOTALSUM,ITEMCODE)
Is there anyway to make this work?

how to differentiate columns based on if else in sql

i have a order table with columns scheduled_arrival_date and actual_arrival_date , i need to find out which order delivered early and late and i need to differentiate orders based on that(two columns should be created ) , as i don't have permission to create new table so i need get this from query.
i tried this, but am getting in single column
SELECT order.id,order.item,
CASE WHEN scheduled_arrival_date >= actual_arrival_date
THEN 'late'
WHEN scheduled_arrival_date <= actual_arrival_date
THEN 'Early'
END as delivered
FROM order
SELECT order.id, order.item, 'late' AS late FROM order WHERE scheduled_arrival_date > actual_arrival_date
UNION ALL
SELECT order.id, order.item, 'early' AS early FROM order WHERE scheduled_arrival_date <= actual_arrival_date
This query is definely not optimized, but it will work. The first query gather all late shippings and put 'late' into the late column. The second one do the exact same trick but with early, and we union all of the result together.
However, i don't really understand why you want two columns, it looks weird this way, your initial request was much better IMO.
PS: Note that you should not use <= and >= in both of your condition, there is a conflit for the equal case
As you want to create a pie diagram it seems to me that you are only interested in the numbers (counts) of the two cases. You can do that like this:
SELECT COUNT(CASE WHEN actual_arrival_date-scheduled_arrival_date>0 THEN 1 END) late,
COUNT(CASE WHEN actual_arrival_date-scheduled_arrival_date<=0 THEN 1 END) early
FROM order

I want to display the bill amount for productId on the basis of particular date for'31-jan-2016' and '31-mar-2016'

I want to display the bill amount for productId on the basis of particular date for '31-jan-2016' and '31-mar-2016' but the query display the Same bill amount for both dates. Suggest a query.
My query
Select productId,
sum(billAmount)as'31jan',
sum(billAmount)as '31Mar'
from test
where billDate='31-jan-2016 '
and '31-mar-2016'
group by productId;
The phrase
where billDate='31-jan-2016 'and '31-mar-2016'
doesn't mean what you think it means. '31-mar-2016' isn't a comparison expression. You probably want
where (billDate='something' OR billDate='anotherthing')
But, also, your date formatting isn't following the SQL standard. You may want dates formattted as '2016-03-31' instead. That's a guess, because you did not mention the data type of your billDate column.
Finally, you probably need to study up on how to use GROUP BY and SUM expressions.
Conditional aggregation seems like one approach to take:
Select productId,
sum(case when billDate = '2016-01-31' then billAmount else 0 end) as amount_20160131,
sum(case when billDate = '2016-03-31' then billAmount else 0 end) as amount_20160331
from test
where billDate in ('2016-01-31', '2016-03-01')
group by productId;
Notes:
This uses ISO standard date formats, YYYY-MM-DD.
Only use single quotes for string and date constants, not for column aliases.
The use of the case inside the sum() solves your problem.

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

Using Sum inside a Case statement in 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'