I have two tables(table1 and table2). 'id' in table2 is a fk(from table 1). table2 describes the table1 and for the same 'id' from table1, table2 has multiple records. Please note that table2 can have other 'categories' as well(other than just 'veg' and 'non-veg').
table1
---------------------
id amount purchase_date
1 100 1/1/22
2 200 2/1/22
3 300 3/2/21
---------------------------
table2
---------------------------------
id amount category desc
1 100 veg abc
1 100 veg xyz
1 100 non-veg def
1 100 non-veg jkl
2 300 veg abc
2 300 veg xyz
2 300 non-veg def
2 300 non-veg jkl
2 300 hot-veg bvn
2 300 mad-veg lji
-----------------------------------------
The result I want : For each id, one record for 'veg' and one for 'non-veg'. The desc column doesnt matter much to me(any one is fine in the result)
------------------------
id amount category
1 100 veg
1 100 non-veg
2 300 veg
2 300 non-veg
-----------------------
Am trying to join like below but it doesn't work
its giving me multiple records for each of the ids.
select * from
table1 t1
inner join t2 on
t1.id = t2.id and t2.category in ('veg','non-veg')
Just use DISTINCT:
with table1 as
(
SELECT 1 AS ID, 100 AS amount, TO_DATE('01/01/22','DD/MM/YYYY') AS purchase_date FROM DUAL UNION ALL
SELECT 2, 200, TO_DATE('02/01/22','DD/MM/YYYY') FROM DUAL UNION ALL
SELECT 3, 300, TO_DATE('03/02/21','DD/MM/YYYY') FROM DUAL
),
table2 as
(
SELECT 1 AS ID, 100 AS amount, 'veg' AS CATEGORY , 'abc' AS DEC FROM DUAL UNION ALL
SELECT 1, 100, 'veg' , 'xyz' FROM DUAL UNION ALL
SELECT 1, 100, 'non-veg', 'def' FROM DUAL UNION ALL
SELECT 1, 100, 'non-veg', 'jkl' FROM DUAL UNION ALL
SELECT 2, 300, 'veg' , 'abc' FROM DUAL UNION ALL
SELECT 2, 300, 'veg' , 'xyz' FROM DUAL UNION ALL
SELECT 2, 300, 'non-veg', 'def' FROM DUAL UNION ALL
SELECT 2, 300, 'non-veg', 'jkl' FROM DUAL UNION ALL
SELECT 2, 300, 'hot-veg', 'bvn' FROM DUAL UNION ALL
SELECT 2, 300, 'mad-veg', 'lji' FROM DUAL
)
SELECT DISTINCT T2.id , T2.amount , T2.category
FROM table1 t1
INNER JOIN table2 t2 ON t1.id = t2.id AND t2.category IN ('veg','non-veg');
Related
Suppose I have the following three tables:
Table1:
ID
Value_1
11
abc
22
def
33
xyz
Table2:
ID
Date_1
11
12-Mar-22
11
01-Jan-23
22
19-Dec-22
22
07-Feb-23
33
07-Mar-22
Table3:
ID
Length_1
11
574
11
1029
22
9220
33
1093
33
876
Now, I need an SQL query that would select each ID with Max Lenth_1 and Max Date_1.
Desired output:
ID
Value_1
Date_1
Length_1
11
abc
01-Jan-23
1029
22
def
07-Feb-23
9220
33
xyz
07-Mar-22
1093
I have used max() fuction to achieve this with left join between 2 tables together, however struggling when I have to use Max () twice with 3 tables. I am relatively new to SQL.
SQL Select Max(Date) out of rows with Duplicate Id
I tried this for two tables
Aggregate before you join the tables:
SELECT t1.id,
t1.value_1,
t2.date_1,
t3.length_1
FROM table1 t1
INNER JOIN (
SELECT id,
MAX(date_1) AS date_1
FROM table2
GROUP BY id
) t2
ON (t1.id = t2.id)
INNER JOIN (
SELECT id,
MAX(length_1) AS length_1
FROM table3
GROUP BY id
) t3
ON (t1.id = t3.id)
Which, for the sample data:
CREATE TABLE Table1 (ID, Value_1) AS
SELECT 11, 'abc' FROM DUAL UNION ALL
SELECT 22, 'def' FROM DUAL UNION ALL
SELECT 33, 'xyz' FROM DUAL;
CREATE TABLE Table2 (ID, Date_1) AS
SELECT 11, DATE '2022-03-12' FROM DUAL UNION ALL
SELECT 11, DATE '2023-01-01' FROM DUAL UNION ALL
SELECT 22, DATE '2022-12-19' FROM DUAL UNION ALL
SELECT 22, DATE '2023-02-07' FROM DUAL UNION ALL
SELECT 33, DATE '2022-03-07' FROM DUAL;
CREATE TABLE Table3 (ID, Length_1) AS
SELECT 11, 574 FROM DUAL UNION ALL
SELECT 11, 1029 FROM DUAL UNION ALL
SELECT 22, 9220 FROM DUAL UNION ALL
SELECT 33, 1093 FROM DUAL UNION ALL
SELECT 33, 876 FROM DUAL;
Outputs:
ID
VALUE_1
DATE_1
LENGTH_1
11
abc
2023-01-01 00:00:00
1029
22
def
2023-02-07 00:00:00
9220
33
xyz
2022-03-07 00:00:00
1093
fiddle
One option is to use subqueries selecting max values from tables 2 and 3:
Select t1.ID, t1.VALUE_1,
(Select Max(DATE_1) From Table2 Where ID = t1.ID) "DATE_1",
(Select Max(LENGTH_1) From Table3 Where ID = t1.ID) "LENGTH_1"
From Table1 t1
Order By t1.ID
... another one is to use analytic function with distinct keyword but it could be performance costly with big datasets:
Select DISTINCT
t1.ID, t1.VALUE_1, Max(t2.DATE_1) OVER(Partition By t1.ID) "DATE_1", Max(t3.LENGTH_1) OVER(Partition By t1.ID) "LENGTH_1"
From Table1 t1
Inner Join Table2 t2 ON(t2.ID = t1.ID)
Inner Join Table3 t3 ON(t3.ID = t1.ID)
Order By t1.ID
... both with your sample data:
WITH
Table1 (ID, VALUE_1) AS
(
Select 11, 'abc' From Dual Union All
Select 22, 'def' From Dual Union All
Select 33, 'xyz' From Dual
),
Table2 (ID, DATE_1) AS
(
Select 11, To_Date('2022-03-12', 'yyyy-mm-dd') From Dual Union All
Select 11, To_Date('2023-01-01', 'yyyy-mm-dd') From Dual Union All
Select 22, To_Date('2022-12-19', 'yyyy-mm-dd') From Dual Union All
Select 22, To_Date('2023-02-07', 'yyyy-mm-dd') From Dual Union All
Select 33, To_Date('2022-03-07', 'yyyy-mm-dd') From Dual
),
Table3 (ID, LENGTH_1) AS
(
Select 11, 574 From Dual Union All
Select 11, 1029 From Dual Union All
Select 22, 9220 From Dual Union All
Select 33, 1093 From Dual Union All
Select 33, 876 From Dual
)
results as:
ID VALUE_1 DATE_1 LENGTH_1
---------- ------- --------- ----------
11 abc 01-JAN-23 1029
22 def 07-FEB-23 9220
33 xyz 07-MAR-22 1093
Select t1.id, t1.value1, max(t2.date_1) date_1, max(t3.length_1)t3
from table_1 t1
left join table_2 t2 on t1.id=t2.id
left join table_3 t3 on t1.id=t3.id
group by t1.id, t1.value1
order by 1
I have two tables and want to get data from one table based on the values got from Listtagg in the second table:
T1
ID Name
==============
1 Name1
2 Person2
3 Someone3
4 Mr.4
T2
ID Acct
===============
1 1234
1 5678
2 1234
3 5678
3 8769
4 1234
My listagg query on T2 has returned the following:
Acct Id
====== ========
1234 1,2,4
5678 1,3
I need the result with Names from other table something like:
Acct Id Name
====== ======== ==========
1234 1,2,4 Name1, Person2, Mr.4
5678 1,3 Name1, Someone3
Why would you first aggregate IDs, and then put effort in splitting them to collect NAMEs? Do it immediately. Not that it can't be done (it can, in a relatively simple manner, but - why?!?).
Sample data is from line #1 - 15; query you might need begins at line #16.
SQL> with
2 t1 (id, name) as
3 (select 1, 'Name1' from dual union all
4 select 2, 'Person2' from dual union all
5 select 3, 'Someone3' from dual union all
6 select 4, 'Mr4' from dual
7 ),
8 t2 (id, acct) as
9 (select 1, 1234 from dual union all
10 select 1, 5678 from dual union all
11 select 2, 1234 from dual union all
12 select 3, 5678 from dual union all
13 select 3, 8769 from dual union all
14 select 4, 1234 from dual
15 )
16 select b.acct,
17 listagg(b.id, ', ') within group (order by b.id) id,
18 listagg(a.name, ', ') within group (order by b.id) name
19 from t1 a join t2 b on a.id = b.id
20 group by b.acct;
ACCT ID NAME
---------- ---------- --------------------
1234 1, 2, 4 Name1, Person2, Mr4
5678 1, 3 Name1, Someone3
8769 3 Someone3
SQL>
#Littlefoot's answer is absolutely correct. But just as an addition: don't use listagg if you are going to split those aggregated values. Just use collect() aggregate function to get needed data as a collection.
For example:
select
cast(collect(level) as sys.odcinumberlist) as varray_of_numbers,
cast(collect(level) as ORA_MINING_NUMBER_NT) as nested_table_of_numbers,
cast(collect(sys.ku$_objnum(level)) as sys.KU$_OBJNUMSET) as nested_table_of_objnum
from dual connect by level<=3;
--Result:
VARRAY_OF_NUMBERS NESTED_TABLE_OF_NUMBERS NESTED_TABLE_OF_OBJNUM(OBJ_NUM)
------------------------- ------------------------------ ------------------------------------------------------------
ODCINUMBERLIST(1, 2, 3) ORA_MINING_NUMBER_NT(1, 2, 3) KU$_OBJNUMSET(KU$_OBJNUM(1), KU$_OBJNUM(2), KU$_OBJNUM(3))
Update: This is a query for your tables, as you asked in the comment:
select b.acct,
cast(collect(b.id) as ORA_MINING_NUMBER_NT) as nested_table_of_numbers,
cast(collect(a.name) as ORA_MINING_VARCHAR2_NT) as nested_table_of_varchar2
-- listagg(b.id, ', ') within group (order by b.id) id,
-- listagg(a.name, ', ') within group (order by b.id) name
from t1 a join t2 b on a.id = b.id
group by b.acct;
Full example:
with
t1 (id, name) as
(select 1, 'Name1' from dual union all
select 2, 'Person2' from dual union all
select 3, 'Someone3' from dual union all
select 4, 'Mr4' from dual
),
t2 (id, acct) as
(select 1, 1234 from dual union all
select 1, 5678 from dual union all
select 2, 1234 from dual union all
select 3, 5678 from dual union all
select 3, 8769 from dual union all
select 4, 1234 from dual
)
select b.acct,
cast(collect(b.id) as ORA_MINING_NUMBER_NT) as nested_table_of_numbers,
cast(collect(a.name) as ORA_MINING_VARCHAR2_NT) as nested_table_of_varchar2
-- listagg(b.id, ', ') within group (order by b.id) id,
-- listagg(a.name, ', ') within group (order by b.id) name
from t1 a join t2 b on a.id = b.id
group by b.acct;
I am performing some data quality checks to identify bad data, I am unable to figure out how I can perform a check-such that the data is accurately mapped based on Value 1 vs Value 2.
I ultimately need to identify all IDs in T1 that have incorrect mapping in T2.I have used the following code but doesn't seem to give desired result. The mapping is not in the database and is a rule based on which the data needs to be entered.
- When value in: Apples,Bananas,Cherries,Pears,Kiwis - then it should be mapped to Fruit
- when value in: Cheese - then Cheese
- when value in: Cashews,Almonds - then Nuts
- when value in: Skittles - then Candy
- when value in: Chocolate - then null
Edit: I have added the desired output.
SELECT t1.id, t2.*
FROM t1,t2,t3
WHERE
t1.id = t2.id
AND (
(t2.value1_id IN (01,04,05,08,09) AND t2.value2_id <> 2)
OR (t2.value1_id = 02 and t2.value2_id <> 3)
OR (t2.value1_id IN (03,10) and t2.value2_id <> 1)
OR (t2.value1_id = 06 AND t2.value2_id <> 4)
OR (t2.value1_id = 07 AND t2.value_id IS NOT NULL)
)
T1
ID
1
2
3
4
5
6
7
T2
T1.ID Value1_ID Value2_ID
1 01 2
1 02 3
1 03 1
2 04 2
2 05 2
2 02 3
2 06 4
2 07
3 08 2
3 02 3
4 09 2
4 10 1
5 02 2
5 10 1
6 04 3
6 10 2
7 07 2
T3
ID Value1
01 Apples
02 Cheese
03 Cashews
04 Bananas
05 Cherries
06 Skittles
07 Chocolate
08 Pears
09 Kiwis
10 Almonds
T4
ID Value2
1 Nuts
2 Fruit
3 Cheese
4 Candy
Desired Output:
T1.ID Value1_ID Value2_ID
5 02 2
6 04 3
6 10 2
7 07 2
T1.ID 5, value1_id 02 is in the desired output as Cheese is mapped to Fruit
T1.ID 6, value1_id 04 - Bananas is mapped to Cheese
T1.ID 6, value1_id 10 - Almonds is mapped to Fruit
T1.ID 7, value1_id 07 - Chocolate is mapped to Fruit when it should be null
One of the problems is that - when looking at T2 - it is not easy to tell whether a "mapping" is correct or not.
When creating the test data for T1 and T2, we have used CHARs for VALUE1_IDs, in order to make the subsequent queries a bit more "readable".
Tables
create table T1( id primary key )
as
select 1 from dual union all
select 2 from dual union all
select 3 from dual ;
create table T2 ( id, value1_id, value2_id )
as
select 1, '01', 2 from dual union all
select 1, '02', 3 from dual union all
select 1, '03', 1 from dual union all
select 2, '04', 2 from dual union all
select 2, '05', 2 from dual union all
select 2, '02', 3 from dual union all
select 2, '06', 4 from dual union all
select 2, '07', null from dual union all
select 3, '08', 2 from dual union all
select 3, '02', 3 from dual union all
select 4, '09', 2 from dual union all
select 4, '10', 1 from dual ;
Refactored query
--
-- find incorrect mappings
--
select t2.*, 'T1 id not valid' as status
from t2
where t2.id not in ( select id from T1 )
union all
select t2.*, 'value1_id <-> value2_id mapping incorrect '
from t1 join t2 on t1.id = t2.id
where
( t2.value1_id in ('01','04','05','08','09') and t2.value2_id <> 2 )
or
( t2.value1_id = '02' and t2.value2_id <> 3 )
or
( t2.value1_id in ('03','10') and t2.value2_id <> 1 )
or
( t2.value1_id = '06' and t2.value2_id <> 4 )
or
( t2.value1_id = '07' and t2.value2_id is null )
;
-- result
ID VALUE1_ID VALUE2_ID STATUS
4 10 1 T1 id not valid
4 09 2 T1 id not valid
2 07 NULL value1_id <-> value2_id mapping incorrect
DBfiddle
ALTERNATIVE
Another possibility may be: create a table, containing all valid mappings, in "human readable" form, and use it to validate the mappings stored in T2. However, use whatever approach you are more comfortable with - as long as you get the correct results. Example (tested w/ Oracle 12c, 18c)
-- in addition to tables T1, T2, T3, and T4: table with correct mappings
create table map( category, product )
as
select 'Fruit', 'Apples' from dual union all
select 'Cheese', 'Cheese' from dual union all
select 'Nuts', 'Cashews' from dual union all
select 'Fruit', 'Bananas' from dual union all
select 'Fruit', 'Cherries' from dual union all
select 'Candy', 'Skittles' from dual union all
select 'Candy', 'Chocolate' from dual union all
select 'Fruit', 'Pears' from dual union all
select 'Fruit', 'Kiwis' from dual union all
select 'Nuts', 'Almonds' from dual;
-- make sure that the entries in the MAP table tie in with T3 and T4
alter table map
add (
constraint m_pk primary key ( category, product )
, constraint m_category_fk foreign key ( category ) references T4 ( value2 )
, constraint m_product_fk foreign key ( product ) references T3 ( value1 )
) ;
Find incorrect mappings
-- T2 rows containing incorrect (invalid) mappings
-- -> all rows MINUS the correct ones
select T2.id, T2.value1_id, T2.value2_id
from T2
minus (
select T2.id, T2.value1_id, T2.value2_id
from T2
join (
--
select T4.id categoryid, T3.id productid, M.category, M.product
from T4
join map M on T4.value2 = M.category
join T3 on T3.value1 = M.product
--
) C -- correct mappings
on
C.productid = T2.value1_id
and C.categoryid = T2.value2_id
) ;
-- result
ID VALUE1_ID VALUE2_ID
2 07 NULL
DBfiddle
I would highly recommend that you create a table to represent the one-to-many relationship between T4 and T3. This would represent a first step towards fixing your design, while providing a simple way to solve your current question.
Here is a CREATE TABLE ... AS SELECT order that initializes such a table with your sample data :
create table cat AS
SELECT 1 t3_id, 2 t4_id FROM DUAL
UNION ALL SELECT 4, 2 FROM DUAL
UNION ALL SELECT 5, 2 FROM DUAL
UNION ALL SELECT 8, 2 FROM DUAL
UNION ALL SELECT 9, 2 FROM DUAL
UNION ALL SELECT 2, 3 FROM DUAL
UNION ALL SELECT 3, 1 FROM DUAL
UNION ALL SELECT 10, 1 FROM DUAL
UNION ALL SELECT 6, 4 FROM DUAL
UNION ALL SELECT 7, NULL FROM DUAL
;
With this table in place, indentifiying records incorrectly mapped is as simple as :
SELECT t2.*
FROM t2
WHERE t2.Value2_ID IS NOT NULL AND NOT EXISTS (
SELECT 1 FROM cat WHERE cat.t3_id = t2.Value1_ID AND cat.t4_id = t2.Value2_ID
)
This DB Fiddle demo with your sample data yields :
T1_ID | VALUE1_ID | VALUE2_ID
----: | --------: | --------:
5 | 2 | 2
6 | 4 | 3
6 | 10 | 2
7 | 7 | 2
Hint to further improve your design : you have a one-to-many relationship between T4 (families of aliments) and T3 (aliments). The classic way to represent this is to add a column in the child table (T3) that references the parent table.
If you can't create a table with the mappings from fruit to categories and you know that the values are static then just include the mappings into your query using a nested sub-query or a sub-query factoring clause:
Oracle Setup:
create table T2 ( id, value1_id, value2_id ) as
select 1, '01', 2 from dual union all
select 1, '02', 3 from dual union all
select 1, '03', 1 from dual union all
select 2, '04', 2 from dual union all
select 2, '05', 2 from dual union all
select 2, '02', 3 from dual union all
select 2, '06', 4 from dual union all
select 2, '07', null from dual union all
select 3, '08', 2 from dual union all
select 3, '02', 3 from dual union all
select 4, '09', 2 from dual union all
select 4, '10', 1 from dual union all
select 5, '02', 2 from dual union all
select 5, '10', 1 from dual union all
select 6, '04', 3 from dual union all
select 6, '10', 2 from dual union all
select 7, '07', 2 from dual;
Query:
WITH mappings ( name, category ) AS (
SELECT '01', 2 FROM DUAL UNION ALL
SELECT '02', 3 FROM DUAL UNION ALL
SELECT '03', 1 FROM DUAL UNION ALL
SELECT '04', 2 FROM DUAL UNION ALL
SELECT '05', 2 FROM DUAL UNION ALL
SELECT '06', 4 FROM DUAL UNION ALL
SELECT '07', NULL FROM DUAL UNION ALL
SELECT '08', 2 FROM DUAL UNION ALL
SELECT '09', 2 FROM DUAL UNION ALL
SELECT '10', 1 FROM DUAL
)
SELECT *
FROM T2 t
WHERE NOT EXISTS (
SELECT 1
FROM mappings m
WHERE t.value1_id = m.name
AND ( t.value2_id = m.category
OR ( t.value2_id IS NULL AND m.category IS NULL ) )
);
Results:
ID | VALUE1_ID | VALUE2_ID
-: | :-------- | --------:
5 | 02 | 2
6 | 04 | 3
6 | 10 | 2
7 | 07 | 2
db<>fiddle here
How do I search with multiple criteria on the same column.
T1 has the IDs.
T2:
ID T1_ID(FK) Value
1 1 Apple
2 1 Orange
3 1 Kiwi
4 2 Orange
5 2 Kiwi
6 3 Pear
7 3 Berry
8 3 Orange
9 4 Apple
10 5 Apple
11 5 Apple
12 5 Kiwi
Output:
T2_ID(FK) Value
1 Apple
1 Orange
1 Kiwi
select t2.t1_id, t2.value
from t1, t2
where t1.id = t2.id
and t2.value in ('Apple','Orange','Kiwi')
group by t1.id having count(t2.value)=3
Is this query correct? Doesn't it also bring t2_id = 5 because #5 matches with apple and kiwi although apple is duplicate?
You don't need to join t1 and you need COUNT(DISTINCT column_name):
SQL Fiddle
Oracle 11g R2 Schema Setup:
CREATE TABLE t2 (ID, T1_ID, Value ) AS
SELECT 1, 1, 'Apple' FROM DUAL UNION ALL
SELECT 2, 1, 'Orange' FROM DUAL UNION ALL
SELECT 3, 1, 'Kiwi' FROM DUAL UNION ALL
SELECT 4, 2, 'Orange' FROM DUAL UNION ALL
SELECT 5, 2, 'Kiwi' FROM DUAL UNION ALL
SELECT 6, 3, 'Pear' FROM DUAL UNION ALL
SELECT 7, 3, 'Berry' FROM DUAL UNION ALL
SELECT 8, 3, 'Orange' FROM DUAL UNION ALL
SELECT 9, 4, 'Apple' FROM DUAL UNION ALL
SELECT 10, 5, 'Apple' FROM DUAL UNION ALL
SELECT 11, 5, 'Apple' FROM DUAL UNION ALL
SELECT 12, 5, 'Kiwi' FROM DUAL;
Query 1:
select t1_id,
LISTAGG( value, ',' ) WITHIN GROUP ( ORDER BY value ) As "values"
from t2
where value in ('Apple','Orange','Kiwi')
group by t1_id
having count( DISTINCT value) = 3
Results:
| T1_ID | values |
|-------|-------------------|
| 1 | Apple,Kiwi,Orange |
Query 2:
You can also do it using collections:
CREATE TYPE STRINGLIST IS TABLE OF VARCHAR2(10);
/
SELECT *
FROM (
SELECT t1_id,
CAST( COLLECT( value ORDER BY value ) AS STRINGLIST ) AS "values"
FROM t2
GROUP BY t1_id
)
WHERE STRINGLIST( 'Apple', 'Kiwi', 'Orange' ) SUBMULTISET OF "values"
Results:
| T1_ID | values |
|-------|-------------------|
| 1 | Apple,Kiwi,Orange |
Neea a help with grouping in sql.
I've table like
id1 id2 type
1 1 300
1 3 300
1 2 300
1 5 300
2 2 100
2 5 200
2 7 300
4 3 100
4 9 300
4 2 300
I need id1 that is mapped to one type only,
For eg, id1 '1' is mapped only to type 300, so it should only be retrieved If there is more than one type mapped to an id1 it shouldnt be retrieved. Please help.
Here is what I have attempted. But it will handle only for type 300.I need to retrieve all the id1's which are mapped to one particular type alone. So if id1 '2' is mapped for type '100' alone, it should also be retrieved.
SELECT distinct id1 from ID_TABLE where type = 300 and id1 not in
(SELECT id1 from type_table where type in (100, 200, 250))
and id1 in ( SELECT id1 FROM ID_TABLE type=300)
order by id1
SQL Fiddle
Oracle 11g R2 Schema Setup:
CREATE TABLE tbl ( id1, id2, type ) AS
SELECT 1, 1, 300 FROM DUAL
UNION ALL SELECT 1, 3, 300 FROM DUAL
UNION ALL SELECT 1, 2, 300 FROM DUAL
UNION ALL SELECT 1, 5, 300 FROM DUAL
UNION ALL SELECT 2, 2, 100 FROM DUAL
UNION ALL SELECT 2, 5, 200 FROM DUAL
UNION ALL SELECT 2, 7, 300 FROM DUAL
UNION ALL SELECT 4, 3, 100 FROM DUAL
UNION ALL SELECT 4, 9, 300 FROM DUAL
UNION ALL SELECT 4, 2, 300 FROM DUAL
UNION ALL SELECT 4, 4, 200 FROM DUAL
UNION ALL SELECT 5, 2, 200 FROM DUAL
UNION ALL SELECT 5, 4, 200 FROM DUAL;
Query 1:
SELECT id1,
MIN( type )
FROM tbl
GROUP BY id1
HAVING COUNT( DISTINCT type ) = 1
Results:
| ID1 | MIN(TYPE) |
|-----|-----------|
| 1 | 300 |
| 5 | 200 |
After the group by below you may still have multiple id1 so having will limit to only those situations when there is a single id1 for type. Using MIN as an arbitrary aggregator here as there is only one value anyway:
SELECT MIN(id1), type
FROM type_table
GROUP BY type
HAVING COUNT(id1)=1;