CASE WHEN after THEN or Select value from other table - sql

I need to do this:
SELECT
COLUMN1,
COLUMN2,
CASE SOMETHING WHEN 0 THEN 'SOMETHING'
ELSE
CASE SOMETHING1 WHEN 'SOMETHING2' THEN (Here I need my value from other table)
ELSE
...
ELSE
...
END
END
AS SOMETHINGSPECIAL
...
...
...
Entire select is horribly complicated sorry.
In the place after THEN in () I need to take out specific value from other table.
I have tried almost everything there is from joins, to put there SELECT WHERE or CASE WHEN statement it always end up with some error.
Keyword missing etc.
Also maybe problem is inside () there is long concatenate:
''
I need to put that specific value from other table into that concatenate.
It either doesn't want to allow me to use other CASE WHEN after that THEN or I'm doing something wrong.
EDIT (sorry cant post entire query dont wanna have problems in work):
SELECT
A.SOMETHING
CASE WHEN A.LIST_ID IN ('something','something') THEN ' (MY VALUE FROM OTHER TABLE HERE) '
END
AS SOMETHINGSPECIAL
FROM SOMETABLE
...
(MY VALUE FROM OTHER TABLE HERE) I tried to put there Select statement condition, Case statement to take out that one value from other table but it just gives me error.

You can use a correlated subquery:
(CASE SOMETHING
WHEN 0 THEN 'SOMETHING'
ELSE (CASE SOMETHING1
WHEN 'SOMETHING2' THEN (select value from othertable ot where ot.col = x.col)
ELSE . . .
Do note that you don't need nested cases. You could write this as:
(CASE WHEN SOMETHING = 0 THEN 'SOMETHING'
WHEN SOMETHING1 = 'SOMETHING2' THEN (select value from othertable ot where ot.col = x.col)
ELSE . . .
END)

You could try joining the table that the other values should come from, that's if there is a link between those tables, so these is what you should do
SELECT
T1.COLUMN1,
T2.COLUMN1,
T.The-column-you-want-from-table2
iNNER JOIN TABLE2 T2 ON T2.cOUMN1 = T1.COLUMN1
So there is no need for a case statement, because from what I can gather from your question, you want a representation value of a value from another table
Here is another more specific example,
Select
Transaction.OrderId
Transaction.OrderDate
Order.StatusDescription
From Transaction
Inner Join Order on Order.OrderID = Transaction.OrderID
In the above example, the StatusDescription is what need from the "other" table, this can be anything from paid,out-of-stock or whatever status. This status in your first table is represented by a number like 1 for paid, 2 for out of stock etc.....
Hope this helps

Related

Struggling with a complicated query on row-based Field/Value table

Bare with me for a little bit of setup here please.
I have a table MAIN that has a Field/Value representation that looks like this:
I have another table called STORE_FLAG:
I am trying to write a parameterized query for which I will be given one FIELD_ID and one or more IDs from the STORE_FLAG table.
What I need to do is select from the MAIN table ROW_IDs where:
for the given FIELD_ID, the VALUE = 'YES' AND
for the given STORE_FLAG_IDS, ANY of those FIELD_IDs correspond to a VALUE = 'x' in the MAIN table.
Not that this would be a good idea, but I cannot pivot the whole table into a column-based table to then do a traditional where clause.
Example:
Given a Field_Id = 1 and a list of StoreIds = (30,50). I would want to return row_ids 1 and 2. This is because row_id 1 and 2 have a field_id 1 with value 'YES' AND at least one of the field_ids 3 and 5 have a value 'x'. But row_id 3 has a value of null for both field_id 3 and 5 and row_id 4 has a field_id 1 with value = 'NO'.
I was thinking something like this:
SELECT DISTINCT ROW_ID FROM MAIN
WHERE (FIELD_ID = :providedFieldId OR FIELD_ID IN (SELECT FIELD_ID FROM STORE_FLAG WHERE ID IN :providedStoreIdList))
AND (FIELD_VALUE = 'YES' OR FIELD_VALUE = 'x')
which (I think) works, but feels naïve to me..? I feel like there is some sort of super duper grouping way to do this, but I can't wrap my head around it. Any suggestions would be really appreciated.
here is a way to do this
select distinct m.row_id
from main m
where m.field_id=:providedFieldId
and m.field_value='YES'
and exists (select 1
from STORE_FLAG sf
join main m2
on sf.field_id=m2.field_id
where sf.id in ('30','50') /* you need to bind the values from :providedStoreIdList using a table function*/
and m2.field_value='x'
and m2.row_id=m.row_id
)
link on how to bind an in list
https://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:110612348061
Your provided solution /query will not work as you say. Because in your last line of query [AND (FIELD_VALUE = 'YES' OR FIELD_VALUE = 'x')] conflict with your requirement . Using your query, you will get ROW_ID if any one is true either FIELD_VALUE = 'YES' OR FIELD_VALUE = 'x'. Which is wrong. You can see below query-
SELECT SUB_QUERY.ROW_ID FROM
(
select DISTINCT MAIN.ROW_ID,MAIN.FIELD_VALUE from STORE_FLAG
RIGHT OUTER JOIN MAIN ON STORE_FLAG.FIELD_ID=MAIN.FIELD_ID
WHERE ((STORE_FLAG.ID IN ('202','203') AND MAIN.FIELD_VALUE='x')
OR (MAIN.FIELD_ID ='1' AND MAIN.FIELD_VALUE='YES'))
) SUB_QUERY
GROUP BY SUB_QUERY.ROW_ID
HAVING (LISTAGG(SUB_QUERY.FIELD_VALUE, ',') WITHIN GROUP (ORDER BY SUB_QUERY.ROW_ID) IN ('YES,x','x,YES'))
I think you need to run and understand my sub query part at first.

How to use subquery in caes statement

I want use select~~~~ subquery in case statement
but I Don't know how to do this
In my idea is
CASE When
(select ...from ... where .. )IS null
then ...
else ...
end as ...
but it's not working
You can do a temp table and query that
with
test as (select names from table where names=smith ) ---You can add in left
--joins here or whatever - again not sure what you are trying to accomplish
select Case when name=smith then "Yes" else Null end as Case_test
from test
Probably an easier way to do it with a subquery but off the top of my head I'm not sure. We would need more detail on what you were trying to accomplish but this would probably do the trick.

SELECT-CASE-IN-SELECT error: [SQL0115] Comparison operator IN not valid. In query db2

i have a problem in a db2 query
I tried run this query
SELECT t.* ,
CASE WHEN column in (SELECT data FROM otherTable WHERE conditions...)
then 5
else 0
end as 'My new data'
FROM table t
WHERE conditions....
But get error
[Error Code: -115, SQL State: 42601] [SQL0115] Comparison operator IN not valid.
When i change the sub-query to where statement like this
SELECT t.*
FROM table t
WHERE column in (SELECT data FROM otherTable WHERE conditions...)
Works fine
Why not work in the case statement? It is a limitation of db2?
And could make an equivalent behavior?
One way to do this is to left join to the table and check if it is not null.
In most cases this will be the fastest way because SQL servers are optimized to perform joins very quickly (but will depend on a number of factors including data model, indexes, data size, etc).
Like this:
SELECT t.* ,
CASE WHEN othertable.data is not null
then 5
else 0
end as 'My new data'
FROM table t
left join otherTable ON otherTable.column = data
WHERE conditions....
Try with using exists condition as below (put the column value in the where clause of subquery) :
SELECT t.* ,
CASE WHEN exists (SELECT data FROM otherTable WHERE conditions... and column=val)
then 5
else 0
end as 'My new data'
FROM table t
WHERE conditions....

SQL SERVER 2005 IF ELSE

I am running following query.
SELECT T1.C1, T2.C2...,
IF( T1.C1<>T2.C1,"Changed","1") AS NewColumn
From T1 INNER JOIN T2
Where condition..
I am getting syntax error for IF statement.
Motive is to compare columns from two different tables, if not equal save as "Changed" in NewColumn of third table.. This is a Insert INTO query.
T-> Table
C->Column
You have to use CASE WHEN in this context.
SELECT T1.C1,
T2.C2...,
CASE WHEN T1.C1<>T2.C1 THEN 'Changed' ELSE '1' END AS NewColumn
FROM T1
INNER JOIN T2
WHERE condition
SELECT T1.C1, T2.C2...,
CASE WHEN T1.C1<>T2.C1 THEN 'Changed' ELSE '1' END AS NewColumn
From T1 INNER JOIN T2 ON ...
Where ...
Others have already mentioned that you should use CASE WHEN ELSE END. The difference between the two is that IF changes the flow of execution of your code - you can conditionally execute code depending on the result of your IF statement. CASE doesn't change the execution flow - it simply lets you check a value, and then get a different result depending on the result.
When you want to use condition checks inside the statement, you should use CASE WHEN
MSDN
But if you have multiline statements, the you can use IF ELSE clause

Use of CASE statement values in THEN expression

I am attempting to use a case statement but keep getting errors. Here's the statement:
select TABLE1.acct,
CASE
WHEN TABLE1.acct_id in (select acct_id
from TABLE2
group by acct_id
having count(*) = 1 ) THEN
(select name
from TABLE3
where TABLE1.acct_id = TABLE3.acct_id)
ELSE 'All Others'
END as Name
from TABLE1
When I replace the TABLE1.acct_id in the THEN expression with a literal value, the query works. When I try to use TABLE1.acct_id from the WHEN part of the query, I get a error saying the result is more than one row. It seems like the THEN expression is ignoring the single value that the WHEN statement was using. No idea, maybe this isn't even a valid use of the CASE statement.
I am trying to see names for accounts that have one entry in TABLE2.
Any ideas would be appreciated, I'm kind of new at SQL.
First, you are missing a comma after TABLE1.acct. Second, you have aliased TABLE1 as acct, so you should use that.
Select acct.acct
, Case
When acct.acct_id in ( Select acct_id
From TABLE2
Group By acct_id
Having Count(*) = 1 )
Then ( Select name
From TABLE3
Where acct.acct_id = TABLE3.acct_id
Fetch First 1 Rows Only)
Else 'All Others'
End as Name
From TABLE1 As acct
As others have said, you should adjust your THEN clause to ensure that only one value is returned. You can do that by add Fetch First 1 Rows Only to your subquery.
Then ( Select name
From TABLE3
Where acct.acct_id = TABLE3.acct_id
Fetch First 1 Rows Only)
Fetch is not accepting in CASE statement - "Keyword FETCH not expected. Valid tokens: ) UNION EXCEPT. "
select name from TABLE3 where TABLE1.acct_id = TABLE3.acct_id
will give you all the names in Table3, which have a accompanying row in Table 1. The row selected from Table2 in the previous line doesn't enter into it.
Must be getting more than one value.
You can replace the body with...
(select count(name) from TABLE3 where TABLE1.acct_id = TABLE3.acct_id)
... to narrow down which rows are returning multiples.
It may be the case that you just need a DISTINCT or a TOP 1 to reduce your result set.
Good luck!
I think that what is happening here is that your case must return a single value because it will be the value for the "name" column. The subquery (select acct_id from TABLE2 group by acct_id having count(*) = 1 ) is OK because it will only ever return one value. (select name from TABLE3 where TABLE1.acct_id= TABLE3.acct_id) could return multiple values depending on your data. The problem is you trying to shove multiple values into a single field for a single row.
The next thing to do would be to find out what data causes multiple rows to be returned by (select name from TABLE3 where TABLE1.acct_id= TABLE3.acct_id), and see if you can further limit this query to only return one row. If need be, you could even try something like ...AND ROWNUM = 1 (for Oracle - other DBs have similar ways of limiting rows returned).