Selecting certain value from row based on another value in same row - sql

I have a following table with following data:
Table
Now I want to get all those users (distinct only) who do not have value 5 in Column B. What I mean is user1 has a value 5 in some row, then all user 1 rows are dismissed.
Following result should be produced:
user2 (because value is null)
user3 (no value 5)
How can I do that?

Perhaps the easiest way to do this would be aggregation by user:
SELECT ColumnA
FROM yourTable
GROUP BY ColumnA
HAVING COUNT(CASE WHEN ColumnB = 5 THEN 1 END) = 0;

One method is aggregation:
select columnA
from t
group by columnA
having sum(case when columnB = 5 then 1 else 0 end) = 0;

You can do this by Minus operator
SELECT distinct colA
FROM have
WHERE colB not in(5)
MINUS
SELECT distinct colA
FROM have
WHERE colB=5;

Using NOT EXISTS you can able to get the result
SELECT DISTINCT T1.ColumnA
FROM TableName T1
WHERE NOT EXISTS (
SELECT * FROM TableName T2 WHERE T2.ColumnA = T1.ColumnA AND T2.ColumnB <> 5
)

One more way -
SELECT DISTINCT T1.ColumnA
FROM TableName T1
WHERE T1.ColumnA NOT IN
(
SELECT T2.ColumnA FROM TableName T2 WHERE T2.ColumnB = 5
)

Related

Match columns 1 if data not found then search column 2 oracle query

I am trying to find a way if data is not found based on col1 of a table then search with other column value
SELECT * FROM TABLE
WHERE COL1='123'
IF NULL
THEN
SELECT * FROM TABLE
WHERE COL2='ABC';
Thanks
This a typical SQL select statement involving an OR expression.
SELECT * from TABLE WHERE Col1 = '123' or Col2 = 'ABC';
You want all rows that satisfy the first condition - but if no row matches, then you want all rows that satisfy the second condition.
I would adress this with a row limiting clause (available starting version 12c):
select *
from mytable
where 'ABC' in (col1, col2)
order by rank() over(order by case col1 = 'ABC' then 1 else 2 end)
fetch first 1 row with ties
This is more efficient than union all because it does not require two scans on the table.
You can use exists with union all :
select t.*
from table t
where col1 = 123 union all
select t.*
from table t
where col2 = 'abc' and
not exists (select 1 from table t1 where t1.col1 = 123);
If you are expecting only one row, you can use:
SELECT t.*
FROM TABLE t
WHERE COL1 = '123' OR COL2 = 'ABC'
ORDER BY (CASE WHEN COL1 = '123' THEN 1 ELSE 2 END)
FETCH FIRST 1 ROW ONLY;
With multiple possible rows in the result set, I would go for:
SELECT t.*
FROM TABLE t
WHERE COL1 = '123' OR
(COL2 = 'ABC' AND
NOT EXISTS (SELECT 1 FROM TABLE t2 WHERE t2.COL1 = '123');

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;

How to delete duplicate results in SQL

I have the following table with two columns which is generated by a query in SQL:
Lookup Value Result
1 2
2 1
4 3
3 4
As you can see it contains duplicate results. I only want it to show the first line and the third line. Does anyone know how to do this in SQL?
Thanks
There are several methods. Here is one using union all:
select t.*
from t
where col1 < col2
union all
select t1.*
from t1
where col1 > col2 and
not exists (select 1 from t t2 where t1.col1 = t2.col2 and t1.col2 = t2.col1);
If you always know that both pairs exist (as in your sample data), you can just use:
select t.*
from t
where col1 < col2;
SELECT DISTINCT
CASE WHEN Lookup Value < Result
THEN Lookup Value
ELSE Result
END as first,
CASE WHEN Lookup Value < Result
THEN Result
ELSE Lookup Value
END as second
FROM YourTable
Create Table T (
[Lookup Value] int,
Result int
)
Insert into T values (1,2),(2,1),(4,3),(3,4)
Select distinct T.[Lookup Value], T.Result
From T
where T.[Lookup Value]<=T.Result

how do I make multiple count under having clause

some sample data:
Id name value ref
1 ab xy
2 aba z
3 ab xy
4 abc def
5 gxr mdy
what I am trying to do is to get the two column that appeared more than once
so row 1 and row 3 would be selected.
select name, value from table_x
where value is not null group by name having count(name) >= 2
and having count(value) >= 2;
got stucked.....
#vkp's answer is correct if you only care about finding the distinct name/value pairs that appear more than once. But if you actually want the individual rows that satisfy the criteria, try this:
SELECT t1.Name, t1.[Value]
FROM Table_X t1
JOIN
(
SELECT Name, [Value]
FROM Table_X
where [Value] IS NOT NULL
GROUP BY Name, [Value]
HAVING COUNT(1) >= 2
) t2 ON t1.Name = t2.Name AND t1.[Value] = t2.[Value]
Your syntax is incorrect. group by name and value and check for count >=2 thereafter.
select name, value
from table_x
where value is not null
group by name, value
having count(*) >= 2;

Efficiently Check for Existence in a Grouped Set

I would like to group over one column checking over some boolean expression in another.
For instance, Say I have a single table:
MyTable
ID | ColA
----------
1 A
1 B
1 C
2 A
2 C
What I would like to do is fetch all records over some boolean selection logic. For instance fetch all IDs where a ColA exists with values A and B
Something similar to
SELECT ID, ColA
FROM MyTable
WHERE ID IN (SELECT ID FROM MyTable WHERE ColA = 'A')
AND ID IN (SELECT ID FROM MyTable WHERE ColA = 'B')
To Return the selection
ID | ColA
---------
1 A
1 B
1 C
Something like the above would work, but it doesn't seem to be all too efficient.
I would write the query using exists and then be sure that some indexes are defined:
SELECT t.ID, t.ColA
FROM MyTable t
WHERE EXISTS (SELECT 1 FROM MyTable t2 WHERE t2.ID = t.ID AND t2.ColA = 'A') AND
EXISTS (SELECT 1 FROM MyTable t2 WHERE t2.ID = t.ID AND t2.ColA = 'B') ;
The index that you want is MyTable(id, ColA).
The query you propose is not too bad for the problem you present. No, it doesn't look so efficient, but what you're asking to do cannot be performed very efficiently.
This variation is at least a little clearer, and perhaps SQL Server's query planner could do something useful with it:
SELECT ID, ColA
FROM MyTable
WHERE ID IN (
SELECT ID FROM MyTable WHERE ColA = 'A'
INTERSECT
SELECT ID FROM MyTable WHERE ColA = 'B'
)