SQL Select query gave a duplicate results - sql

I'm working with the two Oracle example tables, Emp and Dept.
I made this query:
SELECT ENAME,DNAME,LOC FROM EMP INNER JOIN DEPT ON EMP.DEPTNO = 10.
The number 10 is the dept id in the Dept table. I just want to retrieve the records with the deptid 10. The query works but it gave me duplicated records.
Here are the results:
ENAME DNAME LOC DEPTNO
========= ========== ======== ======
JAMES ACCOUNTING NEW YORK 10
CLARK KEN ACCOUNTING NEW YORK 10
JAMES RESEARCH DALLAS 20
CLARK KEN RESEARCH DALLAS 20
JAMES SALES CHICAGO 30
CLARK KEN SALES CHICAGO 30
JAMES OPERATIONS BOSTON 40
CLARK KEN OPERATIONS BOSTON 40
As you can see, the first two records match the query and the same records are duplicated.

You need to change the on criteria and then add where criteria instead:
SELECT ENAME,DNAME,LOC
FROM EMP
INNER JOIN DEPT ON EMP.DEPTNO = DEPT.DEPTNO
WHERE DEPT.DEPTNO = 10

You have no where clause.
SELECT ENAME,DNAME,LOC FROM EMP WHERE DEPTNO = 10

Related

How to transfer Oracle (+) operator with joins to Spark SQL?

I have a part of code in Oracle as this:
SELECT
t1.col1,
t1.col2,
t2.col1,
t2,col2
FROM
t1,
t2
WHERE
t1.col1 <> 121
AND t1.col1 = t2.col1(+)
AND t1.col2 = t2.col2(+)
AND 'ABC' = t2.col3(+)
How to transfer it to Spark SQL assuming tables (t1 and t2) are already registered?
Thanks.
(+) is the old Oracle outer join operator. It was used like this (Scott's sample schema; there are no employees in department 40 so - if you want to display it, you have to use outer join):
SQL> select d.deptno, d.dname, e.ename
2 from emp e,
3 dept d
4 where d.deptno = e.deptno (+) --> outer join
5 order by d.deptno, e.ename;
DEPTNO DNAME ENAME
---------- -------------- ----------
10 ACCOUNTING CLARK
10 ACCOUNTING KING
10 ACCOUNTING MILLER
20 RESEARCH ADAMS
20 RESEARCH FORD
20 RESEARCH JONES
20 RESEARCH SCOTT
20 RESEARCH SMITH
30 SALES ALLEN
30 SALES BLAKE
30 SALES JAMES
30 SALES MARTIN
30 SALES TURNER
30 SALES WARD
40 OPERATIONS --> department with no employees
15 rows selected.
If Spark SQL supports modern ANSI syntax, then the above code can be rewritten to
SQL> select d.deptno, d.dname, e.ename
2 from dept d left join emp e on e.deptno = d.deptno --> outer join
3 order by d.deptno, e.ename;
DEPTNO DNAME ENAME
---------- -------------- ----------
10 ACCOUNTING CLARK
10 ACCOUNTING KING
10 ACCOUNTING MILLER
20 RESEARCH ADAMS
20 RESEARCH FORD
20 RESEARCH JONES
20 RESEARCH SCOTT
20 RESEARCH SMITH
30 SALES ALLEN
30 SALES BLAKE
30 SALES JAMES
30 SALES MARTIN
30 SALES TURNER
30 SALES WARD
40 OPERATIONS --> department with no employees
15 rows selected.
SQL>
See if it helps.
I do not see the point of joining t1 and t2:
SELECT
t1.col1,
t1.col2
FROM
t1
WHERE
t1.col1 <> 121

Apex. How to output NULL values too?

I had a question with a single sql query related to an interactive table in apex
Here, look, I prescribe a request in which I print all the existing artists in the database, but I only have entries where all the fields have values, and those in which at least one NULL are not displayed
select artist.name as "Artist", country.name as "Country" , city.name as "City of foundation", label.name as "Label of records"
from artist, country, city, label
where artist.country = country_id
and artist.city = city_id
and city.country = country_id
and artist.label = label_id
How to fix it?
https://i.stack.imgur.com/ZRYzm.png
As you didn't provide test case (a screenshot isn't quite enough - at least, not to me), I'll try to show what might be going on using Scott's schema.
There are 4 departments: note department 40, and the fact that nobody works in it:
SQL> select * from dept;
DEPTNO DNAME LOC
---------- -------------- -------------
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON
SQL> select * from emp where deptno = 40;
no rows selected
If you want to display all 4 departments and employees who work in them, you'd join EMP and DEPT table. Outer join lets you display department 40 (which, as we saw, has no employees):
SQL> select d.deptno, d.dname, e.ename
2 from dept d left join emp e on e.deptno = d.deptno --> outer join is here
3 order by d.deptno;
DEPTNO DNAME ENAME
---------- -------------- ----------
10 ACCOUNTING CLARK
10 ACCOUNTING MILLER
10 ACCOUNTING KING
20 RESEARCH JONES
20 RESEARCH SMITH
20 RESEARCH SCOTT
20 RESEARCH FORD
20 RESEARCH ADAMS
30 SALES WARD
30 SALES TURNER
30 SALES ALLEN
30 SALES JAMES
30 SALES MARTIN
30 SALES BLAKE
40 OPERATIONS --> this is what you're looking for
15 rows selected.
SQL>
You'd get the same result using the old Oracle's (+) outer join operator. You'd rather switch to modern joins and avoid that operator, though.
SQL> select d.deptno, d.dname, e.ename
2 from dept d, emp e
3 where d.deptno = e.deptno (+) --> the old outer join operator
4 order by d.deptno;
DEPTNO DNAME ENAME
---------- -------------- ----------
10 ACCOUNTING CLARK
10 ACCOUNTING MILLER
10 ACCOUNTING KING
20 RESEARCH JONES
20 RESEARCH SMITH
20 RESEARCH SCOTT
20 RESEARCH FORD
20 RESEARCH ADAMS
30 SALES WARD
30 SALES TURNER
30 SALES ALLEN
30 SALES JAMES
30 SALES MARTIN
30 SALES BLAKE
40 OPERATIONS
15 rows selected.
SQL>

Oracle: Overwrite values in a column with the longest string

I’m running into a problem.
Say, I have columns called “C1, C2, C3....” in a table. I’d like to use the longest string in C1 to replace every other cells in C1 column without disturbing other columns.
I tired several ways but I cannot get my Oracle code run. Could someone please show me a sample code to do this problem? I typed my question using a cellphone so I apologize for not showing you my code. But I think my description is fine... Thank you!
I would use window functions. Oracle has a very convenient functionality with keep:
select max(col1) keep (dense_rank first order by len(col1) desc) over () as col1,
col2, col3, . . .
from t;
You can incorporate this into an update:
update t
set col1 = (select select max(col1) keep (dense_rank first order by len(col1) desc) over () as col1
from t
);
For example:
SQL> select * from test;
DEPTNO DNAME LOC
---------- -------------- -------------
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON
SQL> update test set
2 dname = (select max(dname) --> MAX fixes TOO-MANY-ROWS because ACCOUNTING
3 from test -- and OPERATIONS have same length
4 where length(dname) = (select max(length(dname))
5 from test
6 )
7 );
4 rows updated.
SQL> select * from test;
DEPTNO DNAME LOC
---------- -------------- -------------
10 OPERATIONS NEW YORK
20 OPERATIONS DALLAS
30 OPERATIONS CHICAGO
40 OPERATIONS BOSTON
SQL>
[EDIT, GROUP BY]
Another example is based on a different table, which reflects what you described in a comment. The DEPTNO (department number) is used to "group" employees, and I'm going to update the JOB column value to the longest job name within that department.
Query is similar to the previous one; it just joins appropriate columns (DEPTNO) throughout code.
Sample data:
SQL> select * from test order by deptno, ename;
DEPTNO ENAME JOB
---------- ---------- ---------
10 CLARK MANAGER
KING PRESIDENT --> the longest in DEPTNO = 10
MILLER CLERK
20 ADAMS CLERK
FORD ANALYST
JONES MANAGER --> as long as ANALYST, but MAX(JOB) will return this value
SCOTT ANALYST
SMITH CLERK
30 ALLEN SALESMAN --> the longest in DEPTNO = 30
BLAKE MANAGER
JAMES CLERK
MARTIN SALESMAN
TURNER SALESMAN
WARD SALESMAN
Update and the result:
SQL> update test t set
2 t.job = (select max(t1.job)
3 from test t1
4 where t1.deptno = t.deptno
5 and length(t1.job) = (select max(length(t2.job))
6 from test t2
7 where t2.deptno = t1.deptno
8 )
9 );
14 rows updated.
SQL> select * from test order by deptno, ename;
DEPTNO ENAME JOB
---------- ---------- ---------
10 CLARK PRESIDENT
KING PRESIDENT
MILLER PRESIDENT
20 ADAMS MANAGER
FORD MANAGER
JONES MANAGER
SCOTT MANAGER
SMITH MANAGER
30 ALLEN SALESMAN
BLAKE SALESMAN
JAMES SALESMAN
MARTIN SALESMAN
TURNER SALESMAN
WARD SALESMAN

select how many DEPTNO's exists for each LOC plus number of EMP's

I guess messed up the joins...
Single DEPT has many LOCations, every DEPT should have a sum of its EMPs. I need to show DISTINCT LOCs, number of LOCs per DEPT and sum of EMPS in each DEPT - without dividing the locations.
With tables DEPT & EMP like this:
SELECT DEPTNO, DNAME, LOC FROM DEPT;
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON
50 NONE DALLAS
select ENAME, DEPTNO from EMP;
SMITH 20
ALLEN 30
WARD 30
JONES 20
MARTIN 30
BLAKE 30
CLARK 10
SCOTT 20
KING 10
TURNER 30
ADAMS 20
JAMES 30
FORD 20
MILLER 10
CURT 40
Can't properly add the below subquery into my WITH... clause below. Need to select how many DEPTNO's exists for each LOC plus give a number of EMP's in each DEPT like here (plus location number) - it should use 2 different kinds of summaries in:
select e.deptno, count(e.deptno) from emp e
group by e.deptno;
10 3
20 5
30 6
40 1
Here is what I did:
WITH workers_per_dept as
(SELECT
d.LOC LOC,
d.deptno DEPTNO,
count(e.empno) EMP_NUMBER
FROM dept d
LEFT OUTER JOIN emp e ON (e.deptno = d.deptno)
GROUP BY d.LOC,d.deptno
ORDER BY d.deptno)
select
d.LOC LOCATION,
count(d.LOC) LOCATIONS_PER_DEPT,
workers_per_dept.EMP_NUMBER
from DEPT d, workers_per_dept
WHERE d.LOC = workers_per_dept.LOC
GROUP BY d.LOC, workers_per_dept.EMP_NUMBER
ORDER BY 1;
I receive this (should be groupped by LOC with):
BOSTON 1 1
CHICAGO 1 6
DALLAS 2 0
DALLAS 2 5
NEW YORK 1 3
(result should have not repeated LOC's - 'DALLAS 2 0' should be skipped)
Here is the query. You need to group by location and count distinct occurrences of Dept's in each group:
select d.loc,
count(distinct d.deptno) depts,
count(e.ename) emps
from dept d
left join emp e on d.deptno = e.deptno
group by d.loc
Stupid me... but finally did it myself
it was so easy...
SELECT d.LOC LOCATION,
(select count(d.LOC) FROM DEPT l WHERE l.LOC=d.LOC) LOCS,
(select count(e.deptno) FROM EMP e WHERE e.DEPTNO = d.DEPTNO) EMPS
FROM DEPT d;
Thanks for help!!!

How to solve oracle joins when trying to give input dynamically

I am lucky and i am new to oracle.
I need to retrieve the data from emp table and dept table based on given input deptno and JOB
SELECT
ENAME, E.DEPTNO, JOB , LOC FROM
EMP E , DEPT D where e.deptno=&dno and job ='&JOB' ;
if I enter 10 and clerk
If I write query like this it needs to display only MILLER Record only but the output like as below
MILLER 10 CLERK NEW YORK
MILLER 10 CLERK DALLAS
MILLER 10 CLERK CHICAGO
MILLER 10 CLERK BOSTON
But i need output like
MILLER 10 CLERK NEW YORK
because he belongs to 10th dept and the location is NEW YORK
Please help me on this.
You need to join emp and dept table try
SELECT
ENAME, E.DEPTNO, JOB , LOC FROM
EMP E , DEPT D where e.deptno=&dno
and e.deptno=d.deptno
and job ='&JOB' ;
But i need output like
MILLER 10 CLERK NEW YORK
Then you MUST join both the tables on DEPTNO. You are doing a CARTESIAN join, and therefore it returns you all the 4 rows from DEPT table for one row in EMP table.
You have missed the JOIN condition. So, you need to add this condition:
WHERE e.deptno= d.deptno
Test case:
SQL> SELECT ENAME,
2 E.DEPTNO,
3 JOB ,
4 LOC
5 FROM EMP E ,
6 DEPT D
7 WHERE e.deptno= d.deptno --> Join condition
8 AND E.DEPTNO = &DNO
9 AND job ='&JOB';
Enter value for dno: 10
old 8: AND E.DEPTNO = &DNO
new 8: AND E.DEPTNO = 10
Enter value for job: CLERK
old 9: AND job ='&JOB'
new 9: AND job ='CLERK'
ENAME DEPTNO JOB LOC
---------- ---------- --------- -------------
MILLER 10 CLERK NEW YORK
SQL>