SQL select rows with only a certain value in them - sql

I have a table as such
Col 1 Col 2 Col 3
1 A 1
2 A 2
3 B 1
4 C 1
5 C 2
6 D 1
How do I only get unique rows which have Col 3 = 1?
I want to get rows 3 and 6 (Col 2 = B and D respectively). I do not want A nor C since they have Col 3 = 2 as well.
I've tried something along the lines of:
select col 2 from table group by col 2 having count(col 3) = 1
But that only brings up Col 2 for results so I'm uncertain if Col 3 contents = 1 or not.
EDIT: Sorry guys maybe I've not worded my question clearly. I want to get all of the rows of Col 2 which contain only Col 3 = 1 AND ONLY 1.
So if I tried WHERE Col 3= 1, it would return 4 rows because A has 1. But since A also has a row where Col 3 = 2, I do not want that, same for C. From this example table, I would want the end result to only show 2 rows, B and D.
My example table is an example, I actually have about 5000 rows to filter through, otherwise I'd do as you guys have suggested :)

SELECT col2
FROM your_table
GROUP BY col2
HAVING MAX(col3) = 1 AND MIN(Col3) = 1
Or
SELECT a.col2
FROM your_table a
WHERE a.col3=1 AND NOT EXISTS(SELECT *
FROM your_table b
WHERE a.col2=b.col2 AND b.col3<>1)

What you are probably looking for is WHERE clause.
SELECT * FROM YouTable WHERE col3 = 1 AND col2 in ('B','D');

;with T ([Col 1], [Col 2], [Col 3]) as
(
select 1, 'A', 1 union all
select 2, 'A', 2 union all
select 3, 'B', 1 union all
select 4, 'C', 1 union all
select 5, 'C', 2 union all
select 6, 'D', 1
)
select *
from T
left outer join
(
select distinct [Col 2]
from T
where [Col 3] <> 1
) as T2
on T.[Col 2] = T2.[Col 2]
where T.[Col 3] = 1 and
T2.[Col 2] is null

It's a bit hard to know exactly what you're trying to get, but this is my best guess:
SELECT * FROM theTable WHERE col2 NOT IN
(SELECT col2 FROM theTable WHERE col3 <> 1)

SELECT * FROM #temp t1
WHERE EXISTS
(
select Col2 from #Temp t2
WHERE t2.Col2 = t1.Col2
group by col2
having count(col3) = 1
)
tested with MS SQL2008 and the following (so if my answer is not the correct one it may halp others test theirs...):
CREATE TABLE #temp
(
Col1 INT,
Col2 CHAR(1),
Col3 INT
)
INSERT INTO #Temp
(Col1, Col2, Col3)
SELECT 1,'A',1
UNION
SELECT 2,'A',2
UNION
SELECT 3,'B', 1
UNION
SELECT 4,'C',1
UNION
SELECT 5,'C',2
UNION
SELECT 6,'D',1
SELECT * FROM #temp t1
WHERE EXISTS
(
select Col2 from #temp t2
WHERE t2.Col2 = t1.Col2
group by col2
having count(col3) = 1
)
DROP TABLE #temp

Related

How can I aggregate the columns with other data?

As a part of output from my joins in SP is like :
Col1 col2
A 1
B 1
C 2
C 1
I have another table that has all the possible values in Col1 (A,B,C,D,E,F) [The values are not known and as best practice I don't want to hardcode these values. ]
Expected output in SQL is as shown below
Col1 1 2
A Yes No/Null
B Yes No
C Yes Yes
D No No
E No No
F No No
Appreciate the help I have relatively less experience in SQL and would appreciate if someone could help me understand how I can achieve this.
You can do JOIN with conditional aggregation :
with cte as (
< query >
)
select c.col1,
max(case when t1.col2 = 1 then 'Yes' end),
max(case when t1.col2 = 2 then 'Yes' end)
from cte c LEFT JOIN
table t1
on t1.col1 = c.col1
group by c.col1;
Following SQL pivot query can be used if you can use '1/0' instead of 'YES/NO'
select
*
from (
select
letters.col1, mydata.col2
from (
select 'A' as col1 union all select 'B' union all select 'C' union all select 'D' union all select 'E' union all select 'F'
) letters
left join (
select 'A' as col1, 1 as col2 union all
select 'B' as col1, 1 as col2 union all
select 'C' as col1, 2 as col2 union all
select 'C' as col1, 1 as col2
) mydata
on mydata.col1 = letters.col1
) data
PIVOT (
count( col2 )
FOR col2
IN (
[1],[2]
)
) PivotTable

SQL Server - Select if one of all columns are unique

I want to select if one row where multiple columns are the same. For example:
col1 col2 col3 col4
a b 1 2
b b 1 2
a c 1 2
b b 1 3
a c 2 1
Condition: Select only if values of columns (col1, col2, col3) are different from other rows and value of col4 is max of rows which are the same.
For example expected Output is:
a b 1 2
b b 1 3
a c 1 2
a c 2 1
Yes possible, just use group by with max aggregation as
with tab(col1,col2,col3,col4) as
(
select 'a','b',1,2 union all
select 'b','b',1,2 union all
select 'a','c',1,2 union all
select 'b','b',1,3 union all
select 'a','c',2,1
)
select col1, col2, col3, max(col4) as col4
from tab
group by col1, col2, col3;
col1 col2 col3 col4
a b 1 2
a c 1 2
a c 2 1
b b 1 3
Rextester Demo
Mandatory NOT EXISTS solution... your condition written as a not exist query:
DECLARE #t TABLE (col1 varchar(100), col2 varchar(100), col3 int, col4 int);
INSERT INTO #t VALUES
('a', 'b', 1, 2),
('a', 'c', 1, 2),
('a', 'c', 2, 1),
('b', 'b', 1, 2),
('b', 'b', 1, 3);
SELECT *
FROM #t AS t
WHERE NOT EXISTS (
SELECT 1
FROM #t AS dup
WHERE dup.col1 = t.col1
AND dup.col2 = t.col2
AND dup.col3 = t.col3
AND dup.col4 > t.col4 -- outer row has smaller col4
)
Demo on DB Fiddle

Pivoting row's to columns

How to achieve the below??
Anyone help me out
col_1 col_2
A 1
B 1
C 1
B 2
C 4
A 2
A 6
Output:
A B C
1 1 1
2 2 4
6
This will do the job, but it seems like quite an odd thing to want to do, so I am probably missing something?
CREATE TABLE #table (col1 CHAR(1), col2 INT);
INSERT INTO #table SELECT 'A', 1;
INSERT INTO #table SELECT 'B', 1;
INSERT INTO #table SELECT 'C', 1;
INSERT INTO #table SELECT 'B', 2;
INSERT INTO #table SELECT 'C', 4;
INSERT INTO #table SELECT 'A', 2;
INSERT INTO #table SELECT 'A', 6;
WITH Ranked AS (
SELECT
*,
ROW_NUMBER() OVER (PARTITION BY col1 ORDER BY col2) AS rank_id
FROM
#table),
Numbers AS (
SELECT 1 AS number
UNION ALL
SELECT number + 1 FROM Numbers WHERE number < 50)
SELECT
MAX(CASE WHEN col1 = 'A' THEN col2 END) AS [A],
MAX(CASE WHEN col1 = 'B' THEN col2 END) AS [B],
MAX(CASE WHEN col1 = 'C' THEN col2 END) AS [C]
FROM
Numbers n
INNER JOIN Ranked r ON r.rank_id = n.number
GROUP BY
n.number;
Results are:
A B C
1 1 1
2 2 4
6 NULL NULL
Looks like you are trying to pivot without aggregation? Here is another option:
select A, B, C from
( select col1, col2, dense_rank() over (partition by col1 order by col2) dr from #table) t
pivot
( max(t.col2) for t.col1 in (A, B, C)) pvt;
Also check this out for more examples/discussion: TSQL Pivot without aggregate function

Display record even if it doesn't exist

So I have this table
Col1 Col2 Col3
A 34 X
B 43 L
A 36 L
Now if I query
select * from Table1 where col1 in ('A','B','C')
I am expecting something like
Col1 Col2 Col3
A 34 X
B 43 L
A 36 L
C - -
Is it possible ?
P.S: the - in row C are just to show that the column is empty.
You could create a nested table schema object type:
create type T_List1 as table of varchar2(100);
And then construct your query as follows:
select s.column_value as col1
, nvl(to_char(t.col2), '-') as col2
, nvl(col3, '-') as col3
from Table1 t
right join table(T_List1('A', 'B', 'C')) s
on (t.col1 = s.column_value)
Example:
-- sample of data from your question
with Table1(Col1, Col2, Col3) as(
select 'A', 34, 'X' from dual union all
select 'B', 43, 'L' from dual union all
select 'A', 36, 'L' from dual
) -- actual query
select s.column_value as col1
, nvl(to_char(t.col2), '-') as col2
, nvl(col3, '-') as col3
from Table1 t
right join table(T_List1('A', 'B', 'C')) s --< here list your values
on (t.col1 = s.column_value) -- as you would using `IN` clause
Result:
COL1 COL2 COL3
------------------------
A 36 L
A 34 X
B 43 L
C - -
SQLFiddle Demo
To do this you can use a driver table that has all the values you want returned in it ie:
col1
A
B
C
D
E
Then LEFT JOIN to your table.
SELECT *
FROM driver d
LEFT JOIN Table1 t
ON d.col1 = t.col1
WHERE d.col1 in ('A','B','C')
If you don't want to create an extra nested table type as in Nicholas Krasnov's answer or don't want to create a separate temporary table with A,B,C rows then just create a driving table with with clause:
with driving_table(col) AS
(
select 'A' from dual
union
select 'B' from dual
union
select 'C' from dual
)
select dt.col as col1
, nvl(to_char(t.col2), '-') as col2
, nvl(col3, '-') as col3
from Table1 t
right join driving_table dt
on (t.col1 = dt.col)
http://sqlfiddle.com/#!4/112ef/2

problem with select

I have a table with rows with two columns
A 1
A 2
B 1
B 3
C 1
C 2
C 3
and I want to get from this only this ID(a,b or c) which has only 2 rows with value 1,2, so from this table I should get a, bacause b hasn't row with 2, and c has rows with 1 and b, but also has row with c..
What is the simplest way to get this row?
SELECT col1
FROM YourTable
GROUP BY col1
HAVING COUNT(DISTINCT col2) =2 AND MIN(col2) = 1 AND MAX(col2) = 2
Or another way extendible to more than 2 numbers
SELECT col1
FROM yourtable
GROUP BY col1
HAVING MIN(CASE
WHEN col2 IN ( 1, 2 ) THEN 1
ELSE 0
END) = 1
AND COUNT(DISTINCT col2) = 2
select t1.col1
from table as t1
left join table as t2 on (t1.col1 = t2.col1)
where t1.col2 = 1 and t2.col2 = 2;