How can I select unique and duplicated rows exlude with different values - sql

How can I fetch this table as expected in Oracle. I'm try to do this like below select but its not give me the right result. What I expect is fetch only the unique ones and exclude if these is a record like different values. Sorry for if asked before but I couldn't find it.
SELECT *
FROM ...
WHERE number IN ( SELECT name
FROM (SELECT *
FROM table
WHERE number IN ('Mel','Jose','Kim')
) ds
GROUP BY number
HAVING COUNT (*) = 1)
Current result:
number name
aaa Mel
asd Jose
fsa Jose
xdf Jose
zzz Kim
zzz Kim
Expected result:
aaa Mel
zzz Kim

You're close - I think you were just missing the distinct in the count in your having clause.
E.g.:
WITH your_table AS (SELECT 100 nmbr, 'Mel' NAME FROM dual UNION ALL
SELECT 112 nmbr, 'Jose' NAME FROM dual UNION ALL
SELECT 212 nmbr, 'Jose' NAME FROM dual UNION ALL
SELECT 313 nmbr, 'Jose' NAME FROM dual UNION ALL
SELECT 101 nmbr, 'Kim' NAME FROM dual UNION ALL
SELECT 101 nmbr, 'Kim' NAME FROM dual)
-- end of mimicking data in your table
-- you already have this table, so you would just need the below sql:
SELECT min(nmbr) nmbr,
NAME
FROM your_table
GROUP BY NAME
HAVING COUNT(DISTINCT nmbr) = 1;
NMBR NAME
---------- ----
101 Kim
100 Mel
Just to prove that it doesn't matter whether the nmbr column is of NUMBER or VARCHAR2 datatype:
WITH your_table AS (SELECT 'aaa' nmbr, 'Mel' NAME FROM dual UNION ALL
SELECT 'asd' nmbr, 'Jose' NAME FROM dual UNION ALL
SELECT 'fsa' nmbr, 'Jose' NAME FROM dual UNION ALL
SELECT 'xfd' nmbr, 'Jose' NAME FROM dual UNION ALL
SELECT 'zzz' nmbr, 'Kim' NAME FROM dual UNION ALL
SELECT 'zzz' nmbr, 'Kim' NAME FROM dual)
-- end of mimicking data in your table
-- you already have this table, so you would just need the below sql:
SELECT min(nmbr) nmbr,
NAME
FROM your_table
GROUP BY NAME
HAVING COUNT(DISTINCT nmbr) = 1;
NMBR NAME
---- ----
zzz Kim
aaa Mel

You can do by nested sql with the inner part eliminate repeating ones with respect to id & name, and in the outer part eliminate repeating ones with only name like in the following statement :
SELECT MAX(id),name
FROM (SELECT id,name FROM mytable GROUP BY id, name)
GROUP BY name
HAVING COUNT(1) = 1
ORDER BY MAX(id);
OUTPUT:
ID NAME
----- ------
100 Mel
101 Kim
D e m o 1
exactly the same sql works for your second case :
D e m o 2

Related

Concat multiple rows based on If/Then to poulate a 5 digit code

Hoping someone can help.
I have data as follows in two seperate columns in a table called StudentRace
Student_ID RaceCD
---------- ------
123456 1
123456 2
589645 4
987654 3
987654 4
I am looking for a way to combine the data for the students by student id to output into 00000 format. example: Student_ID 123456 RACE: 12000; Student_ID 589645 Race: 00040; Student_ID 987654 Race = 00340. I need to have it be a sub query as it is part of a large report that pulls 50+ fields. If anyone is able to help I would greatly appreciate it. I am using Toads Data Point for Oracle to create my query.
The result can be achieved with a single group by without any joins.
Setup
CREATE TABLE studentrace
(
Student_ID,
RaceCD
)
AS
SELECT 123456, 1 FROM DUAL
UNION ALL
SELECT 123456, 2 FROM DUAL
UNION ALL
SELECT 589645, 4 FROM DUAL
UNION ALL
SELECT 987654, 3 FROM DUAL
UNION ALL
SELECT 987654, 4 FROM DUAL;
Query
SELECT student_id, LPAD (SUM (racecd * POWER (10, 5 - racecd)), 5, '0') AS race
FROM studentrace
GROUP BY student_id;
Result
STUDENT_ID RACE
_____________ ________
589645 00040
987654 00340
123456 12000
You can use a partitioned outer join:
SELECT t.Student_id,
LISTAGG( COALESCE( t.raceCD, 0 ) ) WITHIN GROUP ( ORDER BY r.race )
AS RaceCDs
FROM ( SELECT LEVEL AS race
FROM DUAL
CONNECT BY LEVEL <= 5 ) r
LEFT OUTER JOIN table_name t
PARTITION BY ( t.Student_ID )
ON ( r.race = t.RaceCD )
GROUP BY t.student_id
Which, for your test data:
CREATE TABLE table_name ( Student_ID, RaceCD ) AS
SELECT 123456, 1 FROM DUAL UNION ALL
SELECT 123456, 2 FROM DUAL UNION ALL
SELECT 589645, 4 FROM DUAL UNION ALL
SELECT 987654, 3 FROM DUAL UNION ALL
SELECT 987654, 4 FROM DUAL
Outputs:
STUDENT_ID | RACECDS
---------: | :------
123456 | 12000
589645 | 00040
987654 | 00340
db<>fiddle here

SQL (where in) returns no results

Oracle "table1"
number code
111 aaa
222 bbb
333 aaa
Query
SELECT COUNT(*) AS CNT, CODE
FROM TABLE1
WHERE NUMBER IN (
'444',
'111',
'333',
'222'
) GROUP BY CODE;
Answer
CNT CODE
2 aaa
1 bbb
Need result, please help.
CNT CODE
1 null
2 aaa
1 bbb
I try request with "nvl" but it returns(count) only rows with (null) code, but not count rows.
PS. Sorry for bad English :)
I think you want a left join:
SELECT CODE, COUNT(t1.NUMBER) AS CNT
FROM (SELECT '444' as num FROM DUAL UNION ALL
SELECT '111' as num FROM DUAL UNION ALL
SELECT '333' as num FROM DUAL UNION ALL
SELECT '222' as num FROM DUAL
) x LEFT JOIN
TABLE1 t1
ON t1.NUMBER = x.num
GROUP BY CODE;

Get duplicate employee count department wise in single sql

ID Name dep_id
1 A 1
2 B 2
3 A 1
4 A 2
5 B 2
6 A 2
I think you want to have such a SQL
with tab( ID, Name, dep_id) as
(
select 1,'A',1 union all
select 2,'B',2 union all
select 3,'A',1 union all
select 4,'A',2 union all
select 5,'B',2 union all
select 6,'A',2
)
select name,
count(dep_id) as dept_count
from tab t
group by name
having count(name)>1;
NAME DEPT_COUNT
---- ----------
A 4
B 2
Due to you last edit( which you wanted to add to this answer ), consider grouping also by dept_id :
with tab( ID, Name, dep_id) as
(
select 1,'A',1 union all
select 2,'B',2 union all
select 3,'A',1 union all
select 4,'A',2 union all
select 5,'B',2 union all
select 6,'A',2
)
select name, dept_id,
count(dept_id) as dept_count
from tab t
group by name, dept_id
having count(name)>1;
NAME DEPT_ID DEPT_COUNT
---- ------ ----------
A 2 2
A 1 2
B 2 2

Validate information between 2 tables - Oracle SQL

I have 2 tables that I need to validate some information, for example:
Table A (GTM_LICENSE_LINE):
License Nº - License Line Nº
123 - 123_1
123 - 123_2
Table B (GTM_LICENSE_LINE_ITEM):
License Line Nº - Item Nº
123_1 - XXX
However, I need to validate if there are any licenses lines without a Item nº associated (all lines must have only one Item nº).
My expected result would be "1" if the condition is true (all license line have an associated item) or null if the condition is false. I'm trying to use LEFT JOIN w/ GROUP BY but it's not working for me.
SELECT u.GTM_LICENSE_LINE_GID
FROM GTM_LICENSE_LINE I
LEFT JOIN GTM_LICENSE_LINE_ITEM U
ON I.LICENSE_LINE_GID = U.GTM_LICENSE_LINE_GID
WHERE i.LICENSE_GID = 'ELEB.L001'
AND U.GTM_LICENSE_LINE_GID is null
GROUP BY U.GTM_LICENSE_LINE_GID
HAVING COUNT(*) > 0
How can I do this using Oracle SQL? Any suggestions?
Thanks
I think you're probably after something like this:
WITH table1 AS (SELECT 123 License_num, '123_1' license_line_num FROM dual UNION ALL
SELECT 123 License_num, '123_2' license_line_num FROM dual UNION ALL
SELECT 456 License_num, '456_1' license_line_num FROM dual UNION ALL
SELECT 456 License_num, '456_2' license_line_num FROM dual),
table2 AS (SELECT '123_1' license_line_num, 'XXX' item_num FROM dual UNION ALL
SELECT '456_1' license_line_num, 'YYY' item_num FROM dual UNION ALL
SELECT '456_2' license_line_num, 'ZZZ' item_num FROM dual)
SELECT t1.license_num,
t1.license_line_num,
MIN(CASE WHEN t2.license_line_num IS NULL THEN 0 ELSE 1 END) OVER (PARTITION BY t1.license_num) all_lines_present
FROM table1 t1
LEFT OUTER JOIN table2 t2 ON t1.license_line_num = t2.license_line_num
ORDER BY t1.license_num, t1.license_line_num;
LICENSE_NUM LICENSE_LINE_NUM ALL_LINES_PRESENT
----------- ---------------- -----------------
123 123_1 0
123 123_2 0
456 456_1 1
456 456_2 1
I'm assuming here that there is a unique constraint on table2 where you can have at most one row for each license_line_num.
This works by outer joining the second table to the first (which shouldn't produce any duplicate lines). Then we use a conditional aggregate function (in this case, MIN) to determine that if there is a value from the second table present, we output a 1 otherwise a 0 for each row, before finding the lowest value.
That way, if any of the rows is missing an item row, the lowest value across all rows for each license_num will be 0.
ETA: If you just want a single row per license_num, you can just use a conditional aggregate function instead, e.g.:
WITH table1 AS (SELECT 123 License_num, '123_1' license_line_num FROM dual UNION ALL
SELECT 123 License_num, '123_2' license_line_num FROM dual UNION ALL
SELECT 456 License_num, '456_1' license_line_num FROM dual UNION ALL
SELECT 456 License_num, '456_2' license_line_num FROM dual),
table2 AS (SELECT '123_1' license_line_num, 'XXX' item_num FROM dual UNION ALL
SELECT '456_1' license_line_num, 'YYY' item_num FROM dual UNION ALL
SELECT '456_2' license_line_num, 'ZZZ' item_num FROM dual)
SELECT license_num,
CASE WHEN all_lines_present = 1 THEN 1 END all_lines_present
FROM (SELECT t1.license_num,
MIN(CASE WHEN t2.license_line_num IS NULL THEN 0 ELSE 1 END) all_lines_present
FROM table1 t1
LEFT OUTER JOIN table2 t2 ON t1.license_line_num = t2.license_line_num
GROUP BY t1.license_num)
ORDER BY license_num;
LICENSE_NUM ALL_LINES_PRESENT
----------- -----------------
123
456 1

SQL find nearest number

Say I have a table like the following (I'm on Oracle 10g btw)
NAME VALUE
------ ------
BOB 1
BOB 2
BOB 4
SUZY 1
SUZY 2
SUZY 3
How can I select all rows where value is closest to, but not greater than, a given number. For example if I want to find all the rows where value is closest to 3 I would get:
NAME VALUE
------ ------
BOB 2
SUZY 3
This seems like it should be simple... but I'm having no luck.
Thanks!
SELECT name, max(value)
FROM tbl
WHERE value <= 3
GROUP BY name
This works (SQLFiddle demo):
SELECT name, max(value)
FROM mytable
WHERE value <= 3
GROUP BY name
Based on hagensofts answer:
SELECT name, max(value)
FROM tbl
WHERE value <= 3 AND ROWNUM <=2
GROUP BY name
With ROWNUM you can limit the output rows, so if you want 2 row, then you can limit the rownum.
WITH v AS (
SELECT 'BOB' NAME, 1 value FROM dual
UNION ALL
SELECT 'BOB', 2 FROM dual
UNION ALL
SELECT 'BOB', 4 FROM dual
UNION ALL
SELECT 'SUZY', 1 FROM dual
UNION ALL
SELECT 'SUZY', 2 FROM dual
UNION ALL
SELECT 'SUZY', 3 FROM dual
)
SELECT *
FROM v
WHERE (name, value) IN (SELECT name, MAX(value)
FROM v
WHERE value <= :num
GROUP BY name)
;