SQL return column based on other column - sql

i have
SELECT col, col1 from table
CASE
WHEN other_col = 'Canada' THEN 1
ELSE 2
END AS col2
it works fine, but i want to calculate
col3 based on value from col2
it should be simple col3 = value from col2 / 2
and return it in the same select
How to achieve it?

You can't use the column col2 in an expression like col2 / 2 inside the same select statement.
You can repeat the same CASE statement like this:
SELECT
col,
col1,
CASE WHEN other_col = 'Canada' THEN 1 ELSE 2 END AS col2
CASE WHEN other_col = 'Canada' THEN 0.5 ELSE 1 END AS col3
FROM table
or by nesting the SELECT statement inside another:
SELECT
t.*,
t.col2 / 2 AS col3
FROM (
SELECT
col,
col1,
CASE WHEN other_col = 'Canada' THEN 1 ELSE 2 END AS col2
FROM table
) AS t

The reason you can't use the alias is because of the 'all at once' expression evaluation.
Expressions are not evaluated in order, but 'all at once' which also allows you to do things like
UPDATE Table SET Col1 = Col2, Col2 = Col1...
Which would not be possible if the expressions were processed in order.
IMHO it's easier and clearer to use CTE instead of repeating the CASE.
;WITH CTE AS
(
SELECT col, col1, CASE
WHEN other_col = 'Canada'
THEN 1
ELSE 2
END AS col2
FROM table
)
SELECT *, <Whatever Function On (Col2).
FROM CTE;

You can use a lateral join in Postgres:
SELECT t.col, t.col1, v.col2
FROM table t CROSS JOIN LATERAL
(VALUES (CASE WHEN other_col = 'Canada' THEN 1 ELSE 2 END)
) v(col2);
You can then use v.col2 to your heart's delight in any other expression you want to.

Related

SQL - avoid select if there is pair

Is it possible to write MS SQL query for this case? If there is pair with 1 and -1 , I don't want select those entries at all.
COL1
COL2
NOTE
A
1
I don't want select this entry becase is in pair with A -1
A
-1
I don't want select this entry becase is in pair with A 1
A
1
OK to select - no pair (no -1 for this A )
B
1
OK to select - no pair
C
1
OK to select - no pair
D
1
I don't want select this entry because is in pair with D -1
D
-1
I don't want select this entry because is in pair with D 1
I understand there is 1s and -1s and these are the only possible values for col2. If this is the case and there is at most one row difference, then you can just add the values up:
select col1, sum(col2)
from mytable
group by col1
having sum(col2) <> 0;
If there can be more rows different or there exist other values beside 1 and -1, then we must generate row numbers.
select col1, max(col2)
from
(
select
col1,
col2,
row_number() over (partition by col1, col2 order by col2) as rn
from mytable
) numbered
group by col1, rn
having count(*) = 1;
One method is aggregation. Assuming there are only -1 and 1 and no duplicates with the same sign:
select col1, max(col2), col3
from t
group by col1, col3
having count(*) = 1;
Alternatively, you could use `not exists:
select t.*
from t
where not exists (select 1
from t t2
where t2.col3 = c.col3 and t2.col1 = t.col1 and
t2.col2 = - t.col1
);
If for any value of Col1 sum of 1 and -1 is not 0, it means that it has unpaired value.
try this:
select *
from t
where col1 in
(select col1 from t group by col1 having sum(col2) <> 0);

How to count a number of unique rows considering that A, B row = B, A row

I am a new in SQL therefore sorry in advance for possible mistakes, incorrect questions.
I am trying to solve the following task:
There is a table with two columns.
My task is to COUNT the number of unique rows, considering that the rows which have the same information (regardless of the order) are counted as 1.
EG. row [1] a b and row [2] b a should be counted as 1
So the result of the query should be 3
You can use aggregation:
select (case when col1 < col2 then col1 else col2 end) as least,
(case when col1 < col2 then col2 else col3 end) as greatest,
count(*)
from t
group by (case when col1 < col2 then col1 else col2 end),
(case when col1 < col2 then col2 else col3 end);
Many databases support the least() and greatest() functions which simplify this logic a bit.
Try the following:
select *, count(*)
from
(
select
case when Column2<Column1 then Column2 else Column1 end as Column1,
case when Column1>Column2 then Column1 else Column2 end as Column2
from tab
) as t
group by Column1,Column2
Example here.
Not the most efficient way of doing it, but if you don't need to group by, here is another method:
select
count(distinct case when col2<col1 then concat(col2,col1) else concat(col1,col2) end)
from your_table;

SQL/Oracle return only field with identical value in 2nd column

Need to return column 1 only if identical values are found in 2nd column of a repeating log. If any other value is seen exclude from result.
A 2
A 2
A 2
A 2
A 2
Exlude
B 2
B 1
B 2
B 3
B 2
select b. column1
from
( select *
from table
where column2 != 1
) b
where b.column2 = 2
Results:
A
You could use aggregation and HAVING:
SELECT col1
FROM tab
GROUP BY col1
HAVING COUNT(DISTINCT col2) = 1;
or if you need original rows:
SELECT s.*
FROM (SELECT t.*, COUNT(DISTINCT col2) OVER(PARTITION BY col1) AS cnt
FROM tab t) s
WHERE s.cnt = 1;
If you need the original rows, I would recommend not exists:
select t.*
from t
where not exists (select 1 from t t2 where t2.col1 = t.col1 and t2.col2 <> t.col2);
If you just want the col1 values (which makes sense to me), then I would phrase the aggregation as:
select col1
from t
group by col1
having min(col2) = max(col2);
If you want to include "all-null" as a valid option, then:
having min(col2) = max(col2) or min(col2) is null
Try this query
select column1 from (select column1,column2 from Test group by column1,column2) a group by column1 having count(column1)=1;

Using distinct in case condition sql

Is there a way to use distinct in the case statement in sql ?
For example -
CASE WHEN col1 = 'XYZ' and DISTINCT(col1,col2)
THEN 'Do_This'
ELSE 'Do_That'
END
Unfortunately the usage of DISTINCT inside the case statement as above throws an error.
I'm using postgres/redshift sql.
First of all your objective is not clear but from your query my assumption is as you want to DO_This or Do_That depending on col1 values as 'XYZ' with group by col 1, col2.
SELECT
CASE WHEN COL1 = 'XYZ'
THEN 'DO_THIS'
ELSE 'DO_THAT'
END
FROM
(
SELECT
COL1, COL2
FROM YOUR_TABLE
GROUP BY COL1, COL2
)

Multiple Subqueries and Conditions

If I have a subquery which does the following;
Select
Min(S_Date)
, Col1
, Col2
From
(
Select Dateadd(whatever) as S_Date, Userid
from tbl1 as t
where S_Date >'today'
)
How can I add another clause so that value from Col1 is only selected if another condition is met, i.e col3 = 'doit'. I guess I am trouble understanding how to use two where clauses in different places in a subquery.
You need to use a CASE statement:
SELECT
s_date
,CASE Col3 WHEN 'doit' THEN Col1 ELSE Col2 END AS selection
FROM (
SELECT
Sdate
, Col1
, Col2
, Col3
FROM foo
WHERE s_Date > GETDATE()
) AS sub
To use aggregate functions like MIN() you need to group by the columns you're not aggregating...
Select
Min(S_Date)
, Col1
, Col2
From
(
Select Dateadd(whatever) as S_Date, Userid
from tbl1 as t
where S_Date >'today'
)
GROUP BY
Col1,
Col2
If you then want the non-aggregated columns to be conditional, you again group by those conditional values...
Select
Min(S_Date)
, CASE WHEN col3 = 'doit' THEN Col1 ELSE Col2 END AS conditional_field
From
(
Select Dateadd(whatever) as S_Date, Userid
from tbl1 as t
where S_Date >'today'
)
GROUP BY
CASE WHEN col3 = 'doit' THEN Col1 ELSE Col2 END
I'm not 100% sure what you actually want to achieve though. Do you have a sample set of data, with the results you want, and an explanation of how the results relate to the source?