Using CASE in PostgreSQL to SELECT different FROMs - postgresql

I'll try to create a query where the result can be from two different tables depending on the size of the first table.
Is something comparable even possible?
SELECT
CASE WHEN COUNT(table1.column1) > 5
THEN
column1,
column2,
column3
FROM table1
ELSE
column1,
column2,
column3
FROM table2
END
With this code I got something like this:
ERROR: syntax error at or near ","
LINE 4: column1,

with c (c) as (select count(c1) from t)
select c1, c2, c3
from t
where (select c from c) > 5
union all
select c1, c2, c3
from r
where (select c from c) <= 5
The corresponding columns must be of the same type. Or be casted to the same type.
WITH clause
UNION clause

Related

How to select list of VALUES in redshift?

The following query works in Postgresql but not in Redshift:
WITH bar (baz) AS
(VALUES ('a'), ('b'), ('c'))
SELECT * from bar;
Which gives
baz
---
a
b
c
How can I replicate this behaviour in Redshift?
unfortunately UNION is the only way here:
WITH bar (baz) AS
(select 'a' union select 'b' union select 'c')
SELECT * from bar;
this is also a good option, IF you do NOT want to use 'WITH' option.
select C1, C2, C3 from
(select '2021-10-01' as C1 , '2021-12-31' as C2 , 'Q4' as c3
union all
select '2021-01-01' , '2021-03-31' , 'Q1'
)

Return multiple columns on single CASE DB2

Is it possible to return multiple column on single CASE evaluation in DB2?
below query return single column.
select (case when 1=1 then 0 else 1 end) as col from table;
I need multiple column like
select (case when 1=1 then 0 as col, 1 as col1 else 2 as col1 , 3 as col2 end) from table;
select (case when 1=1 then 0,1 else 2, 3 end)col , col1 from table;
Is coalesce function is use full for above conditions? thanks.
It’s not possible with a single CASE statement in Db2.
But you may use something like below.
select
coalesce(t1.c1, t2.c1, t3.c1) c1
, coalesce(t1.c2, t2.c2, t3.c2) c2
from
(
select tabschema, tabname, rownumber() over (partition by tabschema) rn_
from syscat.tables
) b
left join table(values ('_SYSIBM_', b.tabname)) t1 (c1, c2) on b.tabschema='SYSIBM'
left join table(values ('_SYSCAT_', b.tabname)) t2 (c1, c2) on b.tabschema='SYSCAT'
cross join table(values (b.tabschema, b.tabname)) t3 (c1, c2)
where b.rn_=1;
The sub-select on syscat.tables is constructed to return only one table from each schema just to show the idea (your base table must be there instead of it). "Case condition" here is what you see in the on clause of each join. "Returned values" of this "Case expression" are inside the values clauses.
A CASE statement can be re-written as a UNION. Logically they are the same thing.
So, you could do this
select 0 as col, 1 as col1 from table where 1=1
UNION ALL
select 2 as col, 3 as col1 from table where NOT 1=1 OR 1=1 IS NULL

(impala) AnalysisException: Subqueries are not supported in the select list

I have a query like this, and appearantly Impala doesn't support subqueries in SELECT statement. How can I neatly rewrite it in Impala?
SELECT
col1,
col2,
...
CASE
WHEN (SELECT 1
FROM
table1 x,
table2 y
WHERE
x.id = y.id
LIMIT 1) = 1
THEN
'A'
ELSE
'B'
END
coln
FROM
...
Your query has the following error(s):
AnalysisException: Subqueries are not supported in the select list.
You could try
SELECT col1, col2, ... 'A' coln
FROM ...
WHERE EXISTS (SELECT 1 FROM table1 x, table2 y WHERE x.id = y.id LIMIT 1)
UNION ALL
SELECT col1, col2, ... 'B' coln
FROM ...
WHERE NOT EXISTS (SELECT 1 FROM table1 x, table2 y WHERE x.id = y.id LIMIT 1)
No guarantees, haven't tried it myself.
In general, a cleaner solution is placing the subqueries into the FROM clause, thereby linking the subqueries to the main table through inner or left joins. I usually do this when dealing with complex types in Impala.
However, in your specific example you are trying to do a left join, defining a field for each row which indicates whether the join was successful ('A') or not ('B'). In this case you could do the following:
SELECT
x.id, x.col2, x.col3, ...
CASE
WHEN y.id IS NOT NULL THEN 'A'
ELSE 'B'
END
coln
FROM table1 x LEFT JOIN
table2 y USING (id)
...

Inner Joining a large query with itself

Problem:
I need to remove duplicate pairs from the result of a query
(same problem as described here)
So if the result has (A,B), (B,A), (C,A)
I am only interested in (A,B) and (C,A)
The Complication:
Unlike in the linked question, the data is not available in a table to perform an self join and retrieve easily. It is more in the following state
(SELECT C1, C2 from a mind boggling number of joins and unions)
So I can make it a temp table as follows
SELECT T.C1, T.C2
((SELECT C1, C2 from a mind boggling number of joins and unions)) T1
I would like to perform an inner join to remove duplicate pairs as mentioned above
So is there a way to do that in such a scenario
Below query is syntactically wrong, but hopefully it conveys the idea
SELECT A.C1, A.C2
((SELECT C1, C2 from a mind boggling number of joins and unions)) T1 A
INNER JOIN T1 B
ON A.C1 = B.C1 AND
A.C2 < B.C2
I am running SQL Server 2012
here is one way to achieve what you want with CTEs
you can as well use temporary table to store result and use cte1 alone.
with cte
as
(
select col1, col2 from --- your query here.
)
, cte1
as
(
select col1, col2, row_number() over
( partition by (case when col1 >= col2 then col1
else col2
end) ,
(case when col1 <= col2 then col1
else col2
end) order by (select null)
) as rn
from cte
)
select * from cte1 where rn =1

Aggregate GREATEST in T-SQL

My SQL is rusty -- I have a simple requirement to calculate the sum of the greater of two column values:
CREATE TABLE [dbo].[Test]
(
column1 int NOT NULL,
column2 int NOT NULL
);
insert into Test (column1, column2) values (2,3)
insert into Test (column1, column2) values (6,3)
insert into Test (column1, column2) values (4,6)
insert into Test (column1, column2) values (9,1)
insert into Test (column1, column2) values (5,8)
In the absence of the GREATEST function in SQL Server, I can get the larger of the two columns with this:
select column1, column2, (select max(c)
from (select column1 as c
union all
select column2) as cs) Greatest
from test
And I was hoping that I could simply sum them thus:
select sum((select max(c)
from (select column1 as c
union all
select column2) as cs))
from test
But no dice:
Msg 130, Level 15, State 1, Line 7
Cannot perform an aggregate function on an expression containing an aggregate or a subquery.
Is this possible in T-SQL without resorting to a procedure/temp table?
UPDATE: Eran, thanks - I used this approach. My final expression is a little more complicated, however, and I'm wondering about performance in this case:
SUM(CASE WHEN ABS(column1 * column2) > ABS(column3 * column4)
THEN column5 * ABS(column1 * column2) * column6
ELSE column5 * ABS(column3 * column4) * column6 END)
Try this:
SELECT SUM(CASE WHEN column1 > column2
THEN column1
ELSE column2 END)
FROM test
Try this... Its not the best performing option, but should work.
SELECT
'LargerValue' = CASE
WHEN SUM(c1) >= SUM(c2) THEN SUM(c1)
ELSE SUM(c2)
END
FROM Test
SELECT
SUM(MaximumValue)
FROM (
SELECT
CASE WHEN column1 > column2
THEN
column1
ELSE
column2
END AS MaximumValue
FROM
Test
) A
FYI, the more complicated case should be fine, so long as all of those columns are part of the same table. It's still looking up the same number of rows, so performance should be very similar to the simpler case (as SQL Server performance is usually IO bound).
How to find max from single row data
-- eg (empid , data1,data2,data3 )
select emplid , max(tmp.a)
from
(select emplid,date1 from table
union
select emplid,date2 from table
union
select emplid,date3 from table
) tmp , table
where tmp.emplid = table.emplid
select sum(id) from (
select (select max(c)
from (select column1 as c
union all
select column2) as cs) id
from test
)
The best answer to this is simply put :
;With Greatest_CTE As
(
Select ( Select Max(ValueField) From ( Values (column1), (column2) ) ValueTable(ValueField) ) Greatest
From Test
)
Select Sum(Greatest)
From Greatest_CTE
It scales a lot better than the other answers with more than two value columns.