SQL assigning a value after testing against multiple columns - sql

I have two columns:
INPUT
col1 col2
1 0
1 0
1 0
2 1
2 0
3 0
3 0
3 1
3 1
Let's suppose col1 holds some entity ID number, which is repeated. I'm testing whether this entity ID contains value 1 in col2. So if entity ID has 1 in corresponding col2 then I create another col3 with "NO"/"YES" values or just "0"/"1" accrodingly.
OUTPUT
col1 col3
1 NO
2 YES
3 YES

SELECT Col1, MAX(CASE WHEN col2 = 1 THEN 1 ELSE 0 END) Col3
FROM YourTable
GROUP BY Col1
UPDATED
Well, since the query above doesn't work for you, you can try the following:
SELECT Col1, MAX(Col3) Col3
FROM ( SELECT Col1,
CASE WHEN col2 = 1 THEN 1 ELSE 0 END AS Col3
FROM YourTable) A
GROUP BY Col1

UPDATE table
SET
col3 = DECODE(col2, 1, 'YES', 'NO');
If you want to run this for a given entity id only:
UPDATE table
SET
col3 = DECODE(col2, 1, 'YES', 'NO')
WHERE
col1 = yourid;
If your column 3 does not exist, you'll have to create it before hand anyway:
ALTER TABLE table ADD (col3 NUMBER NOT NULL);

SELECT Col1,
CASE WHEN MAX(Col2) = 1 THEN 'YES' ELSE 'NO' END AS Col3
FROM TableName
GROUP BY Col1
SQLFiddle Demo

SELECT DISTINCT col1,
CASE WHEN EXISTS(SELECT * FROM MyTab WHERE col1 = M.col1 AND col2 = 1)
THEN 'Yes' ELSE 'No' AS col3 FROM MyTab M

Related

Can I change column order in SQL table based on a value that appears in different columns?

I have a table that looks like this:
Column1 | Column2 | Column3| Column4
4 | 3 | 2 | 1
2 | 1
3 | 2 | 1
I want to flip the columns so that 1 always start in column 1 and then the rest of the values follow to the right. Like this:
Column1 | Column2 | Column3 | Column4
1 | 2 | 3 | 4
1 | 2
1 | 2 | 3
This is an example table. The real table is a hierarchy of a company so 1 = CEO and 2 = SVP for example. 1 is always the same name but as the number gets higher (lower in chain of command) the more names that are in that level. I'm hoping for an automated solution that looks for 1, makes that the first column and then populates the columns. I am struggling because the value that 1 represents is in different columns so I can't just change the order of the columns.
I was able to accomplish this using VBA but I would prefer to keep it in SQL.
I don't have any useful code that I have tried so far.
You can use Case expression:
WITH CTE1 AS
(SELECT 4 AS COL1, 3 AS COL2 , 2 AS COL3, 1 AS COL4 FROM DUAL
UNION ALL
SELECT 2, 1, NULL, NULL FROM DUAL
UNION ALL
SELECT 3, 2, 1, NULL FROM DUAL
)
SELECT CASE WHEN COL1 <> 1 THEN 1 ELSE COL1 END AS COL1,
CASE WHEN COL2 <> 2 THEN 2 ELSE COL2 END AS COL2,
CASE WHEN COL3 <> 3 THEN 3 ELSE COL3 END AS COL3,
CASE WHEN COL4 <> 4 THEN 4 ELSE COL4 END AS COL4
FROM CTE1;
You can apply some CASEes checking all possibilities, this is assuming NULLs for missing data:
COALESCE(col4,col3,col2,col1) AS c1,
CASE
WHEN col4 IS NOT NULL THEN col3
WHEN col3 IS NOT NULL THEN col2
WHEN col2 IS NOT NULL THEN col1
END AS c2,
CASE
WHEN col4 IS NOT NULL THEN col2
WHEN col3 IS NOT NULL THEN col1
END AS c3,
CASE
WHEN col4 IS NOT NULL THEN col1
END AS c4
You want to sort the values. A generic SQL solution would use:
select max(case when seqnum = 1 then col end) as col1,
max(case when seqnum = 2 then col end) as col2,
max(case when seqnum = 3 then col end) as col3,
max(case when seqnum = 4 then col end) as col4
from (select col1, col2, col3, col4, col,
row_number() over (order by col) as seqnum
from ((select col1 as col, 1 as which, col1, col2, col3, col4 from t) union all
(select col2 as col, 2 as which, col1, col2, col3, col4 from t) union all
(select col3 as col, 3 as which, col1, col2, col3, col4 from t) union all
(select col4 as col, 4 as which, col1, col2, col3, col4 from t)
) t
where col is not null
) t
group by col1, col2, col3, col4;
This would be simpler in a database that supports lateral joins. And a unique id on each row would also help.

Replace Value in Column with Value in Different Column

I have a dataset that looks like this in SQL.
Col1 Col2 Col3
A 4 1
B 5 NULL
C 6 1
D 7 NULL
E 8 NULL
How do I add a new column with the values in Col2 with the values in Col3 if Col3 = 1, or else keep the existing values in Col2.
Final Expected Output:
Col1 Col2 Col3 Col4
A 4 1 1
B 5 NULL 5
C 6 1 1
D 7 NULL 7
E 8 NULL 8
I tried the coalesce function but I don't think that worked:
SELECT
Col1,
Col2,
Col3,
coalesce(Col3, Col2) AS Col4
FROM table1
Your description suggests a case expression :
select . . .
(case when col3 = 1 then col3 else col2 end) as col4
You could also express the above as
select . . .
(case when col3 = 1 then 1 else col2 end) as col4
For the data you provided, coalesce() should also work.
Try this:
SELECT
Col1,
Col2,
Col3,
CASE WHEN Col3 IS NOT NULL THEN Col3 ELSE Col2 END AS Col4
FROM table1
-- this should do what you want
SELECT
Col1,
Col2,
Col3,
CASE WHEN Col3 = 1 THEN Col3 ELSE Col2 END AS NewCOL
FROM table1
Insert into table2
select
Col1,
Col2,
Col3,
(case when col3 = 1 then 1 else col2 end) as col4
FROM table1

SQL where column equals Val and equals Val2

If you have a table as per bellow:
Col1 Col2
1 1
2 1
3 1
1 2
3 2
2 3
is there a way to write a SQL query where (Col2 =1 and Col2=2) and the result is:
Col1
1
3
You could do this using intersect. Note that this wouldn't work in MySQL.
select col1 from tablename where col2 = 1
intersect
select col1 from tablename where col2 = 2
You can use HAVING with CASE WHEN:
SELECT Col1
FROM your_table
GROUP BY Col1
HAVING SUM(CASE WHEN Col2 = 1 THEN 1 END) > 0
AND SUM(CASE WHEN Col2 = 2 THEN 1 END) > 0;
LiveDemo
With MySQL you can write:
SELECT Col1
FROM your_table
GROUP BY Col1
HAVING SUM(Col2 = 1) > 0
AND SUM(Col2 = 2) > 0;
Self join version:
select distinct t1.col1
from (select col1 from tablename where col2 = 1) t1
join (select col1 from tablename where col2 = 2) t2 on t1.col1 = t2.col1

Distinct by comparing multiple columns SQL

I have a select query
Select col1,col2,col3
from table;
The table contains following rows
col1 col2 col3
A | B | C
B | A | C
C | B | C
I need to get the distinct result which contains a single combination A,B,C by comparing multiple columns.
Result Should be some thing like
col1 col2 col3
A | B | C
the order can be changed of result rows.
How can I achieve this ?
Please try out this, I am not sure about you proper requirement. But on sample data given above. I have came across this solution,
With CTE as
(
Select MIN(col1) as col1 from MyTable
)
Select * from CTE
cross apply
(
Select MIN(col2) as col2 from MyTable
where col2 <> CTE.col1
)as a
cross apply
(
Select MIN(col3) as col3 from MyTable
where col3 not in (CTE.col1,a.col2)
)as b
DEMO HERE
SELECT *
FROM table
WHERE (col1 = 'A' AND col2 = 'B' AND col3 = 'C')
You can also go with this below query if the number of column and the values are known.
The CASE statement is the closest to IF in SQL
SELECT
CASE
WHEN (col1 = 'A' and col2 = 'B' and col3='C') or (col1 = 'C' and col2 = 'A' and col3='B') or (col1 = 'B' and col2 = 'C' and col3='A' )
THEN 1
ELSE 0
END as RESULT, *
FROM table
From the result you can take the required output by checking the value of RESULT==1(integer)
If you want the result as a boolean value then do the CAST like ,
SELECT
CAST(
CASE
WHEN (col1 = 'A' and col2 = 'B' and col3='C') or (col1 = 'C' and col2 = 'A' and col3='B') or (col1 = 'B' and col2 = 'C' and col3='A' )
THEN 1
ELSE 0
END as RESULT_INT)
as RESUTL, *
FROM table

SQL UPDATE Select row based on column cross referenced values

I would like to do an update to a row based on a value in another column.
Example table
Col1 Col2 Col3
'A' | '' | 100
'B' | '' | 120
'C' | 'A' | 0
UPDATE Table SET Col3 = Col3 - 10 WHERE Col1 = 'A'
However, if Col2 is not blank then I want to update the row that has it's value in Col2 so that
UPDATE Table SET Col3 = Col3 - 10 WHERE Col1 = 'C'
would update the Col1 = 'A' row
update
I discovered the following query works for me
UPDATE Table SET col3 = Col3 - 10
WHERE Col2 = '' and Col1 = 'C'
OR Col1 = (SELECT Col2 FROM Table WHERE Col1 = 'C')
where tbl is the table name
update tbl set col3=col3-10
from tbl t
inner join tbl tt
on t.col1=tt.col2 or t.col2=''
where t.col1 = 'C'