CASE SQL Oracle Query - What is wrong? - sql

I have following query to select the view to be used in the query, however I get the error:
FROM keyword not found where expected
select *, (CASE WHEN 'employee' = 'employee' THEN employee ELSE vw END) FROM type1

select type1.*,
(CASE WHEN 'employee' = 'employee'
THEN employee
ELSE vw
END)
FROM type1
I always prefix with the tablename/table alias to the * and it works!!
We just need to specify, fetch all the column from this table, when we specify combination of wildcard and other select expressions!

You cannot use * and individual columns together in select statement.
SELECT (CASE WHEN 'employee' = 'employee' THEN 'employee' ELSE 'vw' END)
FROM dual

You cant do a *, in Oracle without an alias/TableName(.) in front of it. List out the columns you want to see in the result set or add a table alias/tablename.

You cannot set the name of the view the select statement shall retrieve data from in the column list part of the statement.

Related

Select Case when Grouping(Column1) not working in Snowflake

I'm trying to do the following query in Snowflake:
Select case when grouping(column_1) = 'Total'
else column_1 end as column_1
,sum(column_2)
From Table
group by rollup(column_1)
But I keep getting the error: "SQL compilation error: GROUPING function cannot appear outside of SELECT, HAVING, and ORDER BY clauses."
Any suggestions on how to fix this or work arounds?
Try writing the query like this:
select (case when grouping(t.column_1) = 1
then 'Total' else column_1
end) as column_1,
sum(column_2)
From Table t
group by rollup(t.column_1);
That is, qualify the reference in the GROUP BY so it is not resolved to the column alias. Also, note that this fixes the case expression.

SQL comparing each row to a reference row

I am trying to compare each row from a select statement to a reference row.
So to put it into context I would like to find the reference row which is the account details for one of our users.
SELECT id, first_name
FROM account
WHERE id = '100'
Would return the info for the user in question
Then I want to run a SELECT statement to return all users - pretty straightforward
SELECT id,first_name
FROM account
For each row I would like to compare the first_name with the reference row. If it is the same return a '1' if it is different return a '0'
I can do this if I type in the value to compare e.g 'Paul'
SELECT id,first_name,
CASE
WHEN first_name = 'Paul' THEN '1'
ELSE '0'
END
FROM account
But obviously I want to replace Paul with whatever the first_name is from the reference row above.
My googling suggests I need to declare a variable and then something with SELECT INTO a variable
DO $$;
Declare
#reference_first_name text;
BEGIN
SELECT first_name
into #reference_first_name
FROM account
WHERE id = ‘100’
END;
But I can't seem to put it together.
Then to go a step further would it be possible to reference multiple columns?
You could do this simply in a subquery:
demo:db<>fiddle
SELECT
id,
first_name,
CASE
WHEN (SELECT first_name FROM users WHERE id = 100) = first_name THEN 1
ELSE 0
END
FROM users;
Other ways are using a CTE or a JOIN (see fiddle for these versions)
Here's another option using an outer join:
select a.id, a.first_name, case when a.first_name = b.first_name then 1 else 0 end
from account a
left join account b on b.id = 100
Online Demo
Use correlated subquery as :
select a.id, a.first_name,
( select count(*)
from personnel p
where p.id = 100
and upper(p.first_name) = upper(a.first_name) ) as flag
from account a;
provided you have a table called personnel and has an ID fixed for all comparisons.
Rextester Demo

SQL AND Clause only if another value exists

I have a basic SQL query where I am selecting data from a core records table. I want to add an AND clause to my statement to filter out the results based on a table variable, only if data actually exists in there.
SELECT
*
FROM
TABLE
WHERE
field = '123'
AND
(gender IN (SELECT gender FROM #genders))
In this case, I am looking for all records where field = 123. My goal here is to say that if #genders contains records, filter by that as well.
However, if #genders is empty and we don't have any data in it, it should include all records.
How can I go about doing this? The temp tables are created based on the user selecting one or more optional pieces of criteria from the UI. If they choose a gender for example, I put their selections into a temp table and then I need to search records that meet that criteria. However, if they don't select a gender, I want to include all records, regardless of what the main record has for the gender field.
SELECT
*
FROM
TABLE
WHERE
field = '123'
AND ((SELECT count(1) FROM #genders) = 0 OR
(gender IN (SELECT gender FROM #genders)))
You can use IF condition:
IF EXISTS(SELECT gender FROM #genders)
BEGIN
SELECT * FROM TABLE
WHERE field = '123'
AND
(gender IN (SELECT gender FROM #genders))
END
ELSE
BEGIN
SELECT * FROM TABLE
END
You are going to think this is odd but it is efficient
SELECT t.*
FROM TABLE t
JOIN GENDERS g
on g.gender = t.gender
and t.field = '123'
union all
SELECT t.*
FROM TABLE t
where not exists (select 1 from genders)
Maybe I'm under-thinking it, but isn't it just this?
SELECT
*
FROM
TABLE AS t
LEFT JOIN
#genders AS g
ON
g.gender = t.gender
WHERE
field = '123'
AND
(g.gender = t.gender OR g.gender IS NULL);
If your query doesn't get too complicated, I'd recommend an if statement. Once you find yourself continually adding if else statement in there, I'd recommend looking into dynamic SQL.
IF EXISTS(SELECT gender FROM #genders)
BEGIN
SELECT * FROM TABLE
WHERE field = '123'
and gender IN (SELECT distinct gender FROM #genders)
END
ELSE
BEGIN
SELECT * FROM TABLE WHERE field = '123'
END

How Do I Use Case Statement Column In Group By

As stated by the question, I'm trying to formulate a query that has a case statement in the column results, and then I want to include that column in the query's group by statement. To give a concrete example, here is all little of what my query looks like:
SELECT SOME_TABLE_ALIAS.COLUMN1, OTHER_TABLE_ALIAS.COLUMN2,
CASE
WHEN SOME_TABLE_ALIAS.COLUMN3 IS NOT NULL THEN 'A'
ELSE 'B'
END AS CASE_COLUMN
FROM SOME_TABLE SOME_TABLE_ALIAS
... (other table joins and where clauses)
GROUP BY SOME_TABLE_ALIAS.COLUMN1, OTHER_TABLE_ALIAS.COLUMN2, CASE_COLUMN
Before coming here, I checked out a few websites, including this one, to try solve my problem. I've tried adding another alias after the CASE keyword like is shown in the linked web page but have had no luck. The error message I continue to receive is the following:
[Error] Script lines: 127-151 ----------------------
CASE_COLUMN IS NOT VALID IN THE CONTEXT WHERE IT IS USED. SQLCODE=-206, SQLSTATE=42703, DRIVER=3.53.71
Has anyone else run into the issues I'm facing and been able to use a GROUP BY on the results of a CASE statement? Any help would be appreciated. Oh, and the DB2 version is a z/OS instance, version 10 (DSN10015)
The alias isn't available to use in the GROUP BY because when GROUP BY happens the alias isn't defined yet:
Here's the order:
1.FROM
2.WHERE
3.GROUP BY
4.HAVING
5.SELECT
6.ORDER BY
You can work around that with:
SELECT column1,column2,case_column
FROM (
SELECT SOME_TABLE_ALIAS.COLUMN1, OTHER_TABLE_ALIAS.COLUMN2,
CASE
WHEN SOME_TABLE_ALIAS.COLUMN3 IS NOT NULL THEN 'A'
ELSE 'B'
END AS CASE_COLUMN
FROM SOME_TABLE SOME_TABLE_ALIAS
... (other table joins and where clauses)
) a
GROUP BY COLUMN1, COLUMN2, CASE_COLUMN
Or just use the case you use in SELECT in GROUP BY
You can either use the case as is in the group by, like this:
SELECT SOME_TABLE_ALIAS.COLUMN1, OTHER_TABLE_ALIAS.COLUMN2,
CASE
WHEN SOME_TABLE_ALIAS.COLUMN3 IS NOT NULL THEN 'A'
ELSE 'B'
END AS CASE_COLUMN
FROM SOME_TABLE SOME_TABLE_ALIAS
... (other table joins and where clauses)
GROUP BY SOME_TABLE_ALIAS.COLUMN1, OTHER_TABLE_ALIAS.COLUMN2,
CASE
WHEN SOME_TABLE_ALIAS.COLUMN3 IS NOT NULL THEN 'A'
ELSE 'B'
END
or use a sub-query like this:
select COLUMN1, COLUMN2, CASE_COLUMN
from (
SELECT SOME_TABLE_ALIAS.COLUMN1, OTHER_TABLE_ALIAS.COLUMN2,
CASE
WHEN SOME_TABLE_ALIAS.COLUMN3 IS NOT NULL THEN 'A'
ELSE 'B'
END AS CASE_COLUMN
FROM SOME_TABLE SOME_TABLE_ALIAS
... (other table joins and where clauses)
) a
GROUP BY COLUMN1, COLUMN2, CASE_COLUMN

How to summarize SQL table to return value conditionally

I have a table with several rows, and several columns. It looks like this:
Name Description
X PASS
X PASS
X FAIL
I want it to return only one row. If all of them are PASS, return PASS.
If one or more of them are FAIL, then return FAIL.
What's the best way to go about achieving this in SQL Server 2008?
EDIT: The values in the name column will always be the same.
Depending on the database indexes, and assuming you want one row returned per unique name, I would look at the performance of
select
name,
min([description]) as description
from
tableA
group by
name
compared to the other solutions
SELECT TOP 1 CASE Description WHEN 'FAIL' THEN 'FAIL' ELSE 'PASS' END
FROM DaTable
ORDER BY Description
OP: Is it possible that the table is empty? In that case this query won't return any rows, obviously.
EDIT
According to aquinas's comment I created a modified query without ordering:
SELECT CASE COUNT(Description) WHEN 0 THEN 'FAIL' ELSE 'PASS' END
FROM DaTable
WHERE Description = 'FAIL'
This query will return PASS if DaTable is empty.
This is the simplest solution you will find:
SELECT MIN(Description) FROM tbl
If there's at least one FAIL, then our result column will contain FAIL, otherwise, it will contain PASS.
You can use EXISTS to get the existance of a row containing "FAIL".
You could also try something like:
SELECT TOP 1 COALESCE(tFail.Description,t.Description)
FROM myTable AS t
LEFT JOIN myTable AS tFail ON tFail.Name = t.Name AND tFail.Description = 'FAIL'
WHERE t.Name = 'x'
Here is the query:
--DROP TABLE result
CREATE TABLE result(Name varchar(10),Description varchar(20))
--select * from result
INSERT INTO result
VALUES('X','PASS'),('X','PASS'),('X','FAIL')
;WITH CTE(descp,cnt) as (SELECT [description],COUNT(*) as cnt FROM result group by [description])
SELECT CASE WHEN COUNT(*) > 1 then 'FAIL' when COUNT(*)=1 then MAX(descp) else 'PASS' END FROM CTE