Oracle SQL: How to remove duplicate employee Ids from results? - oracle

I need to write query to remove duplicate employee ids among 10,000 results
EmpID name
1 x
1 x
2 y
2 y
3 z
4 A
The result should be only:
EmpID name
3 z
4 A
Select * from EMPLOYEE where ?
How can I do this?

You need aggregation :
select e.empid, e.name
from employee e
group by e.empid, e.name
having count(*) = 1;

You can try below -
Select empid,name from EMPLOYEE
group by empid,name
having count(*)=1

I would really ask you to use other than the GROUP BY method as you will be able to fetch other fields of the EMPLOYEE table along with EMPID and NAME.
Using analytical function
SELECT * FROM
(SELECT T.*, COUNT(1) OVER (PARTITION BY EMPID) AS CNT
FROM EMPLOYEE)
WHERE CNT = 1;
Using NOT EXISTS
SELECT * FROM EMPLOYEE T
WHERE NOT EXISTS
(SELECT 1 FROM EMPLOYEE TIN
WHERE TIN.ID = T.ID AND TIN.ROWID <> T.ROWID);
Cheers!!

Related

FROM keyword not found where expected while filtering data

I got one error
ORA-00923: FROM keyword not found where expected
Here is my query
SELECT * FROM
(SELECT *, (SELECT COUNT(*) FROM invoices) AS numberOfRows
FROM invoices ORDER BY Id DESC) WHERE rownum <= 1
I am begginer in Oracle SQL, but as I see here I have FROM keyword and it looks everythink OK.
I try to modify this query something like but still get another error
ORA-00933: SQL command not properly ended
SELECT * FROM
(SELECT COUNT(*) FROM invoices) AS numberOfRows
FROM invoices ORDER BY Id DESC) WHERE rownum <= 1
What is wrong in first select query ? What is missing ? Since I check everything, start from special character ( . , )
Also I try this kind of solution and get error
ORA-00936: missing expression
SELECT * FROM (SELECT , (SELECT COUNT() FROM invoices) AS numberOfRows FROM invoices ORDER BY Id DESC) WHERE rownum <= 1
The railroad diagram in the documentation:
... shows that you can either use * on its own, or <something>.* along with other columns or expressions. So you need to precede your * with the table name or an alias:
SELECT * FROM
(SELECT i.*, (SELECT COUNT(*) FROM invoices) AS numberOfRows
FROM invoices i ORDER BY Id DESC) WHERE rownum <= 1
If you're on a recent version of Oracle you can do this much more simply with:
select i.*, count(*) over () as numberOfRows
from invoices i
order by id desc
fetch first row only
On older version you still need a subquery, but only one level:
select *
from (
select i.*, count(*) over () as numberOfRows
from invoices i
order by id desc
)
where rownum = 1
db<>fiddle
looks like the FROM is missing from this select "SELECT *,"
SELECT * FROM
(SELECT , (SELECT COUNT() FROM invoices) AS numberOfRows
FROM invoices ORDER BY Id DESC) WHERE rownum <= 1

Concat Results of 2 Select Queries into 1 Column (oracle)

Im trying to insert a record into my table. But there is 1 column in which I want to get concatenated results of 2 select statements. Like the 2 statements will fetch their records and concatenate to form 1 value so that it can be inserted into the column.
insert into ABC (Name,City,Age)
Values ('John',(
(Select City from TableA where ID=1)concat(Select City from TableA where ID=2)),'22')
Or it can be comma separated but I am not getting what to use here.
Try this one:
INSERT INTO ABC (Name, City, Age)
VALUES ('John',
(
(SELECT City FROM TableA WHERE ID = 1) ||
(SELECT City FROM TableA WHERE ID = 2)
),
'22');
But ensure ... WHERE ID = 1 and ....WHERE ID = 2 return one row.
Using a cross join to select from the two tables produces a nice clear statement:
insert into ABC (Name,City,Age)
select 'John', concat(t1.city, t2.city), 22
from TableA t1
cross join TableA t2
where t1.ID = 1
and t2.ID = 2
/
Use CONCAT() or CONCAT_WS() functions for this (reference)
insert into ABC (Name,City,Age) Values (
'John',
CONCAT_WS(' ', (Select City from TableA where ID=1), (Select City from TableA where ID=2)),
'22'
)

Oracle Missing right parenthesis ORA-00907

Consider a database schema with three relations:
Employee (*eid:integer*, ename:string, age:integer, salary:real)
Works (*eid:integer*, *did:integer*, pct_time:integer)
Department(*did:integer*, dname:string, budget:real, managerid:integer)
Query the view above to find the name of the manager who manages most employees. If thesame employee works in several departments, that employee is counted once in each of the
departments. The manager is included in the count the same as all other employees, i.e., based
on his or her records in the Works table.
Why do I get this error:
ORDER BY SUM (EmpCount) DESC)
*
ERROR at line 6:
ORA-00907: missing right parenthesis
Here is my query:
SELECT distinct(MgrName)
FROM ManagerSummary
WHERE MgrID = (SELECT MgrID
FROM ManagerSummary
GROUP BY MgrID
ORDER BY SUM (EmpCount) DESC
LIMIT 1 );
The view is:
CREATE VIEW ManagerSummary (DeptName, MgrID, MgrName, MgrSalary, EmpCount)
AS SELECT d.dname, d.managerid, e.ename, e.salary,
(SELECT COUNT (w.did)
FROM works w
WHERE w.did = d.did
GROUP BY w.did)
FROM employee e, department d WHERE d.managerid = e.eid;
Thank you
Update: Changing LIMIT 1 for WHERE ROWNUM = 1 doesn't help
Try this
SELECT DISTINCT (MgrName)
FROM ManagerSummary
WHERE MgrID = (SELECT MgrId
FROM ( SELECT MgrId, SUM (empcount) AS maxemp
FROM ManagerSummary
GROUP BY MgrId
ORDER BY SUM (empcount) DESC)
WHERE ROWNUM = 1)
You seem to want the name of the manager that has the most employees.
My guess is that you can do this in Oracle as:
select ms.MgrName
from (select ms.*
from ManagerSummary ms
order by EmpCount desc
) ms
where rownum = 1;
It is hard for me to envision a table called ManagerSummary that would have more than one row per MgrId. That's why I don't think aggregation is necessary.
SELECT mgrname
FROM (SELECT mgrname, numemps
FROM (SELECT mgrname, count(*) numemps
FROM mgrsummary
GROUP BY mgrname)
ORDER BY NUMEMPS desc);
Just noticed - this is based on a view. This is ~not~ going to perform well.

vertical output

I have column name in the table:
select LASTNAME
FROM dbo.Employees
WHERE LASTNAME = 'Smith'
and output of the above query is
LASTNAME
Smith
I want output like
LASTNAME
S
m
i
t
h
With a little help of a numbers table.
SQL Server:
select substring(E.LASTNAME, N.N, 1) as LASTNAME
from Employees as E
inner join Numbers as N
on N.N between 1 and len(E.LASTNAME)
order by E.LASTNAME, N.N
Oracle:
select substr(E.LASTNAME, N.N, 1) as LASTNAME
from Employees E
inner join Numbers N
on N.N between 1 and length(E.LASTNAME)
order by E.LASTNAME, N.N;
SQL Fiddle
In SQL Server, if you don't have a table of numbers, then you can use CTE to generate the list:
;with cte (id, start, numb) as
(
select id, 1 start, len(lastname) numb
from employees
union all
select id, start + 1, numb
from cte
where start < numb
)
select c.id, substring(e.lastname, c.start, 1)
from employees e
inner join cte c
on c.start between 1 and len(e.lastname)
and c.id = e.id
order by e.id, e.lastname;
See SQL Fiddle With Demo
----- function for splitting
CREATE FUNCTION [dbo].[SPLIT_Test] (
#string VARCHAR(8000) )
RETURNS #table TABLE (strval VARCHAR(8000))
AS
BEGIN
IF LEN(#string)>=1
BEGIN
DECLARE #fulllen int=LEN(#string),#lastlen int=0
WHILE #fulllen>#lastlen
BEGIN
INSERT INTO #table
SELECT SUBSTRING(#string,1,1)
SET #string= RIGHT(#String, LEN(#String) - 1)
SET #lastlen=#lastlen+1
END
RETURN
END
RETURN
END
---- query
GO
DECLARE #name table(name varchar(500),row int IDENTITY(1,1))
INSERT INTO #name
select LASTNAME
FROM dbo.Employees
WHERE LASTNAME = 'Smith'
DECLARE #Finalname table(name varchar(50))
DECLARE #startrow int =(SELECT MAX(row) FROM #name)
,#endrow int =1
WHILE #startrow>=#endrow
BEGIN
INSERT INTO #Finalname
Select strval from [dbo].[SPLIT_test] ((SELECT name FROM #name where row=#endrow)) WHERE strval<>''-- removing empty spaces
SET #endrow=#endrow+1
END
SELECT * FROM #Finalname

Query to exclude row based on another row's filter

I'm using Oracle 10g.
Question: How can I write query to return just ID only if ALL the codes for that ID end in 6? I don't want ID=1 because not all its codes end in 6.
TABLE_A
ID Code
===============
1 100
1 106
2 206
3 316
3 326
4 444
Desired Result:
ID
==
2
3
You simply want each ID where the count of rows for that id is the same as the count of rows where the third digit is six.
SELECT ID
FROM TABLE_A
GROUP BY ID
HAVING COUNT(*) = COUNT(CASE WHEN SUBSTR(code,3,1) = '6' THEN 1 END)
Try this:
SELECT DISTINCT b.id
FROM (
SELECT id,
COUNT(1) cnt
FROM table_a
GROUP BY id
) a,
(
SELECT id,
COUNT(1) cnt
FROM table_a
WHERE CODE LIKE '%6'
GROUP BY id
)b
WHERE a.id = b.id
AND a.cnt = b.cnt
Alternative using ANALYTIC functions:
SELECT DISTINCT id
FROM
(
SELECT id,
COUNT(1) OVER(PARTITION BY id) cnt,
SUM(CASE WHEN code LIKE '%6' THEN 1 ELSE 0 END) OVER(PARTITION BY id) sm
FROM table_a
)
WHERE cnt = sm

Resources