PostgreSQL: using case to compare values between columns - sql

I would like to compare two columns, A and B.
If Col A and Col B share the same value, I would like Col A to have a no value set.
If Col A and Col B do not share the same value, I would like Col A to keep the original value it has.
Below is what I attempted. However, it returns "true" for all entries in the case column - Col A (corrected).
select *,
case when 'Col A' = 'Col B'
then 'Col A' = null
else 'Col A' = 'Col A'
end as "Col A (corrected)"
from my_table

select
case
when col_a=col_b then null
else col_a
end as col_a_corrected
from my_table

Simply do
select *,
NULLIF(col_a, col_b)
from my_table
The NULLIF returns null if col_a = col_b, otherwise col_a is returned.
https://www.postgresql.org/docs/current/functions-conditional.html#FUNCTIONS-NULLIF

Related

SQL append column at the bottom of another column

What is the best way to append a column at the bottom of another column? So it would look something like this:
column_a column_b
a e
f k
c m
new_column
a
f
c
e
k
m
All i can really find is answers on how to merge two column into one and this is with CONCAT() but nothing about pasting two column ontop of each other.
If you want to keep the order, you could use something like this.
with col_a as (select 'a' as column_a union select 'f' union select 'c'),
col_b as (select 'e' as column_b union select 'k' union select 'm')
select 1 as num_order,
column_a
from col_a
union all
select 2 as num_order,
column_b
from col_b
order by num_order;
Yields:
1,a
1,c
1,f
2,e
2,k
2,m
If the order is irrelevant you can omit the num_order attribute.

Suggested sequence of responses in query

I have such values in the letter column:
A, B, C, D, E, **X**.
I would like the select to return to me such an order of
A, B, **X**, C, D, E.
I tried with ORDER BY, but I don't know if it's a good way, or it should be SELECT Top 2 and next...
If it's only one character:
order by case when MyColumn < 'C' then 1
when MyColumn = 'X' then 2
else 3
end,
MyColumn
In this case you should assign a numeric value to each of the possible values in order to get them in the desired way. It could be something like
order by case when column = 'A' then 1
when column = 'B' then 2
when column = 'C' then 3
when column = 'X' then 4
...
else 99999999
end
This can be done using a case expression to re-position the 'X' between 'B' and 'C' as follows.
order by case when MyColumn = 'X' then 'BB' else MyColumn end

How can I acces the output from the first select statement

I have a table Like this
Col1 | Col2
-----------
a | d
b | e
c | a
Now I want to create an statement to get an output like this:
First| Second
-------------------
a | Amsterdamm
b | Berlin
c | Canada
...
So far I have this consturct what is not working
SELECT *
FROM(
SELECT DISTINCT
CASE
when Col1 IS NULL then 'NA'
else Col1
END
FROM Table1
UNION
SELECT DISTINCT
CASE
when Col2 IS NULL then 'NA'
else Col2
END
FROM Table1
) AS First
,
(
SELECT DISTINCT
when First= 'a' then 'Amsterdam'
when First= 'b' then 'Berlin'
when First= 'c' then 'Canada'
) AS Second
;
can you help me with that
Sorry I have to edit my question to be more specific.
Not as familiar with DB2... I'll lookup if it has a concat function in a sec... and it does.
SELECT First, case when first = 'a' then
concat('This is a ',first)
case when first = 'b' then
concat('To Be or not to ',first)
case else
concat('This is a ',first) end as Second
FROM (
SELECT coalesce(col1, 'NA') as First
FROM Table
UNION
SELECT coalesce(col2, 'NA')
FROM table) SRC
WHERE first <> 'NA'
What this does is generate a single inline view called src with a column called first. If col1 or col2 of table are null then it substitutes NA for that value. It then concatenates first and the desired text excluding records with a first value of 'NA'
Or if you just create an inline table with the desired values and join in...
SELECT First, x.b as Second
FROM (
SELECT coalesce(col1, 'NA') as First
FROM Table
UNION
SELECT coalesce(col2, 'NA')
FROM table) SRC
INNER JOIN (select a,b
from (values ('a', 'This is a'),
('b', 'To B or not to' ),
('c', 'I like cat whose name starts with')) as x(a,b)) X;
on X.a = src.first
WHERE first <> 'NA'
Personally I find the 2nd option easier to read. Though if you have meaning for a,b,c I would think you'd want that stored in a table somewhere for additional access. In code seems like a bad place to store data like this that could change.
Assuming you want
a this is a a
b this is a b
c this is a c
d this is a d
e this is a e
thanks to xQbert
I could solve this problem like this
SELECT FirstRow, concat
(
CASE FirstRow
WHEN 'AN' then 'amerstdam'
WHEN 'G' then 'berlin'
ELSE 'NA'
END, ''
) AS SecondRow
FROM(
Select coalesce (Col1, 'NA') as FirstRow
FROM Table1
UNION
Select coalesce (Col2, 'NA')
FROM Table1) SRC
WHERE FirstRow <> 'NA'
;

Oracle: Get All Rows Except One

I am stuck with a simple query. What i want is to get all rows except one Kindly have a look at the following data.
COL_A COL_B
B D
B (null)
B C
G D
G (null)
G C
I want to get all rows except but B C. Kindly have a look at the sqlfiddle
I have tried to get the rows by anding col_A <> 'B' and col_B <> 'C' but it's not anding the operation. Your help will be much appreciated.
Thanks
One possible solution. Maybe not the most elegant:
select req_for col_A, doc_typ col_B
from a
where (req_for IS NULL OR doc_typ IS NULL)
OR (req_for,doc_typ)
NOT IN (select 'B','C' from dual);
Try
where not(col_A = 'B' and col_B = 'C')
or
where col_A <> 'B' or col_B <> 'C'
Your problem is the NULL values. Here is a concise way of expressing this in Oracle:
where (col_A || col_B) <> 'BC'
Oracle treats NULL values as the empty string in string concatenation.
Ah, negatives. Always causing trouble. With a SQL query like this you have to think about what you want to INCLUDE, not what you want to EXCLUDE.
If you do where nvl(doc_typ,'NA') <> 'C' and nvl(req_for, 'NA') <> 'B';, you aren't including any rows with doc_type of C, and you aren't including any rows with req_for of B.
You want to do where nvl(doc_typ,'NA') <> 'C' or nvl(req_for, 'NA') <> 'B';. This way a doc_type of C will still be included, as long as its req_for isn't also B.
Could you not just remove the unwanted row:
select req_for col_A, doc_typ col_B from a
where NOT (NVL(doc_typ,'NA') = 'C' AND nvl(req_for,'NA') = 'B');
select req_for col_A, doc_typ col_B from a
where req_for||doc_typ != 'BC';
select req_for col_A, doc_typ col_B from a
where case when req_for = 'B' and doc_typ='C' then 0 else 1 end > 0

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).