SQL Select with If statement to assign values - sql

I have a multiple SELECT and trying to add If or Case statement to assign values based on what it is DB. Trying to change Y to DD and blanks to TTTT
My code looks like that
SELECT
wo_1.ata_chapter AS 1,
wo_2.type AS 2,
wo_3.comp_partno AS 3,
' ' AS 4,
wo_5.mel_code AS 5,
WHEN wo_6.hil AS DD
FROM wo_db
I tried CASE
CASE
WHEN wo_6.hil = 'Y'
Then 'DD'
Else 'TTTT'
I tried If as well
IF (wo_6.hil = 'Y', 'DD', Then 'TTTT')

The syntax for case would be:
(CASE WHEN wo_6.hil = 'Y' THEN 'DD' ELSE 'TTTT' END) as xx
The parentheses are not needed (although recommend them), but the END is.
Note: This is based on your code. Your description doesn't specify what to do when the value is neither 'Y' nor blanks.

Related

SQL Server : SUM of column with alphanumeric values

I want to get the sum of a column that is alphanumeric. I want to add numeric values and return column values if not numeric. What I did is a added a CASE WHEN that looks like this
CASE
WHEN intAllocatedResourceperDivision NOT IN ('CL', 'HS', 'HV', 'ML', 'SL', 'VL', 'HC', 'S', '*')
THEN CAST(SUM(ISNULL(CAST(intAllocatedResourceperDivision AS DECIMAL), 0.00)) AS NVARCHAR(250))
ELSE intAllocatedResourceperDivision
END intAllocatedResourceperDivision
So I assume that all numeric values will be added and if values is in ('CL', 'HS', 'HV', 'ML', 'SL', 'VL', 'HC', 'S', '*') it will be returned as is.
But I'm getting
Error converting data type nvarchar to numeric.
Looks like your SUM aggregation is out of place. You only sum if the condition in the case statement is true. Try this:
SUM(case when intAllocatedResourceperDivision NOT IN ('CL','HS','HV','ML','SL','VL','HC','S','*') THEN intAllocatedResourceperDivision else 0 end)
In case you don't know the exact potential combination of non numeric values, you can use the ISNUMERIC function (assuming you're using SQL Server) to test whether or not the value is a number and assign a 0 if it's not, aggregating the final result.
SUM(case when ISNUMERIC(intAllocatedResourceperDivision) = 1 then intAllocatedResourceperDivision else 0 end)
To aggregate the numerical values and also keep non-numerical, you can use a union query as such:
select
cast(SUM(cast(intAllocatedResourceperDivision as decimal(18,2))) as varchar)
from
YOUR_TABLE
where
ISNUMERIC(intAllocatedResourceperDivision) = 1
UNION ALL
select
intAllocatedResourceperDivision
from
YOUR_TABLE
where
ISNUMERIC(intAllocatedResourceperDivision) = 0
This looks like SQL Server syntax. I would recommend using TRY_CONVERT():
TRY_CONVERT(DECIMAL, intAllocatedResourceperDivision) as intAllocatedResourceperDivision
Try this:
select 'CL' as intAllocatedResourceperDivision into #tmp
union select 'HS'union select 'HV'union select 'ML'union select 'SL'union select 'VL'union select 'HC'union select 'S'union select '*'union select '1'union select '4'
select CAST(SUM(ISNULL(CAST(intAllocatedResourceperDivision AS DECIMAL),0.00)) AS nvarchar(250)) as intAllocatedResourceperDivision
from #tmp where intAllocatedResourceperDivision NOT IN ('CL','HS','HV','ML','SL','VL','HC','S','*')
union
select intAllocatedResourceperDivision
from #tmp where intAllocatedResourceperDivision IN ('CL','HS','HV','ML','SL','VL','HC','S','*')

Invalid # of Arguments in a stuff statement with case in SQL

I have to do an insert into a single column/row from a source of multiple values. I'm using the stuff case and I'm so close, but I'm missing one of the expected returns, so I'm not sure what I need to do to make sure I get the results I'm looking for.
HERE is my statement:
SELECT STUFF((SELECT CASE WHEN TotalAmount <=0 THEN 'C' ELSE 'D' END FROM Charges WHERE ChargeNumber=123 FOR XML Path('')), 1,1,'')
The results are D D D
But, I actually have four rows, so I should see D D D D
How can I make sure that I don't delete my first return, if that's what it is doing. WHen I try 0,1 it fails.
Any advice is greatly appreciated, thank you! (Running in SQL Server 2012)
For your query you don't need STUFF(). Just do:
SELECT (CASE WHEN TotalAmount <= 0 THEN 'C' ELSE 'D' END)
FROM Charges
WHERE ChargeNumber = 123
FOR XML Path('');
STUFF() is only needed when you have a separator. It removes the separator at the beginning of the result string. Without a separator it removes the first value, which is why you are missing one of the 'D's.
If you change the 2nd 1 to a 0 it works.
For example,
DECLARE #Charges TABLE (ChargeNumber int, TotalAmount int)
INSERT INTO #Charges VALUES (123, 100), (123, 200), (123,100), (123, 300)
SELECT STUFF((SELECT CASE WHEN TotalAmount <=0
THEN 'C' ELSE 'D'
END
FROM #Charges
WHERE ChargeNumber = 123 FOR XML Path('')), 1,0,'')
Gives output:
DDDD

PostgreSQL, SELECT CASE COALESCE

I need to 'name' categories: mycat is a text column with possible values '0' to '4'.
SELECT CASE mycat
WHEN '0' THEN 'ZERO'
WHEN '1' THEN 'ONE'
WHEN '2' THEN 'TWO'
WHEN '3' THEN 'THREE'
WHEN '4' THEN 'OTHER'
END AS my_category,
COALESCE(SUM(col1), 0),
COALESCE(SUM(col2), 0),
COALESCE(SUM(col3), 0)
FROM mytable
GROUP BY mycat
ORDER BY mycat;
That works OK, but I have some an error in my program which very rarely writes null (or '' as I can see in pgAdmin). In such cases I have to treat that '' the same as '0'.
But I can't get that!
I try like this:
SELECT CASE COALESCE(mycat, '0')
But this doesn't solve it at all.
How to get that '' will be summed and grouped together with '0' category?
PostgreSQL 9.3, Windows.
you need to use COALESCE in the group by and order by also similar to how you planned to change the case expression, but postgres is giving error , so another option is to wrap your statement in a subquery and do group by
SELECT my_category,
COALESCE(SUM(col1), 0),
COALESCE(SUM(col2), 0),
COALESCE(SUM(col3), 0)
FROM
(
SELECT CASE coalesce(mycat ,'0')
WHEN '0' THEN 'ZERO'
WHEN '1' THEN 'ONE'
WHEN '2' THEN 'TWO'
WHEN '3' THEN 'THREE'
WHEN '4' THEN 'OTHER'
WHEN '' THEN 'ZERO'
END AS my_category,
col1,
col2,
col3
FROM mytable
) T
GROUP BY my_category
ORDER BY my_category
You can have this without subquery. You could repeat the expression in the GROUP BY and ORDER BY clause. But it's much simpler to use the ordinal number of the output column instead:
SELECT CASE mycat
WHEN '1' THEN 'ONE'
WHEN '2' THEN 'TWO'
WHEN '3' THEN 'THREE'
WHEN '4' THEN 'OTHER'
ELSE 'ZERO' -- catches all other values
END AS my_category
, COALESCE(SUM(col1), 0) AS sum1
, COALESCE(SUM(col2), 0) AS sum2
, COALESCE(SUM(col3), 0) AS sum3
FROM mytable
GROUP BY 1
ORDER BY 1;
I chose the simplest and fastest code. The ELSE branch catches 0, '' and NULL - or any other value not yet filtered! But you say there are no others.
A couple of rants:
mycat is 'text' column with possible values '0' to '4'.
This is wrong in two ways.
Obviously, there are empty strings ('') and / or NULL values, too.
With that fixed, integer, smallint, of "char" with a CHECK cnstraint would be sensible choices for the data type. (Maybe even enum.) text, not so much.
To find out your actual range of values:
SELECT mycat, count(*) AS ct
FROM mytable
GROUP BY 1
ORDER BY 2 DESC;
If your client obfuscates NULL and empty values, test with mycat IS NULL. You need to know and understand the difference in many situations.
This orders by the resulting text in my_category like: ONE, OTHER, THREE, TWO, ZERO? I doubt you want that.

oracle adding, then avg with null

I have sql like:
select avg(decode(type, 'A', value, null) + decode(type, 'B', value, null)) from table;
The problem with this is some of these types can be null, so the addition part will result in null because adding anything to null makes it null. So you might think I could change the decode from null to 0, but that seems to make the avg() count it as part of it's averaging, but it shouldn't/I don't want it counted as part of the average.
Ideally the addition would just ignore the nulls and just not try to add them to the rest of the values.
So let's say my numbers are:
5 + 6 + 5
3 + 2 + 1
4 + null + 2
They total 28 and I'd want to divide by 8 (ignore the null), but if I change the null to 0 in the decode, the avg will then divide by 9 which isn't what I want.
As written, your code should always return null, since if the first decode returns value, then the second decode must always return null. I'm going to assume that you made an error in genericizing your code and that what you really meant was this:
avg(decode(type1, 'A', value1, null) + decode(type2, 'B', value2, null))
(Or, instead of type1, it could be a.type. The point is that the fields in the two decodes are meant to be separate fields)
In this case, I think the easisest thing to do is check for nulls first:
avg(case when type1 is null and type2 is null then null
else case type1 when 'A' then value1 else 0 end
+ case type2 when 'B' then value2 else 0 end
end)
(I replaced decode with case because I find it easier to read, but, in this case decode would work just as well.)
This is overcomplicated to do a sum here. Juste output the values with a CASE, and you are done.
SELECT AVG(
CASE WHEN type = 'A' OR type = 'B'
THEN value
ELSE null
END
)
FROM table
A simple workaround would be to calculate the average yourself:
select
-- The sum of all values with type 'A' or 'B'
sum(decode(type, 'A', value, 'B', value, 0)) /
-- ... divided by the "count" of all values with type 'A' or 'B'
sum(decode(type, 'A', 1, 'B', 1, 0))
from table;
A SQLFiddle example
But the way AVG() works, it would probably be sufficient, if you just removed the addition and put everything in a single DECODE()
select avg(decode(type, 'A', value, 'B', value, null)) from table
The logic here is a bit complicated:
select avg((case when type = 'A' then value else 0 end) + (case when type = 'B' then value else 0 end))
from table
where type in ('A', 'B')
The where clause guarantees that you have at least one "A" or "B". The problem is arising when you have no examples of "A" or "B".

How do I build this simple mySQL query?

I would like to select all rows where field A is 'x' and field B is one of 'w', 'y' or 'z'.
A and B are both strings, and I would like case to be ignored.
SELECT *
FROM table
WHERE LOWER(A) = 'x'
AND LOWER(B) IN ('w', 'y', 'z')
select * from tablename where LCASE(A) ='x' and LCASE(B) in('w','y','z')
I would like to select all rows where field A is 'x' and field B is one of 'w', 'y' or 'z'
... WHERE fldA = "x" AND fldB IN ("w", "y", "z") ...
A and B are both strings, and I would like case to be ignored.
Just make sure that columns' collations are set to case insensitive type, eg utf8_unicode_ci, utf8_german_ci, latin2_general_ci (the suffix _ci is the key).