Get Unique column value along with other. Columns when using inner join - sql

I have following query and I need unique value for column
Select unique(t.id), log.*
from tableA log
inner join tableT t on t.id1=log.id1
where log.time>=(somedate)
and log.time<(somedate)
and ref-id=20
and ref-id=30
and t.id not in (select unique t.id
from tableA log
inner join tableT t on t.id1=log.id1
where log.time>=(somedate)
and log.time<(somedate)
and ref-id=20
and ref-id=30);
I am not getting unique values for t.id.Can anyone please help ? I am using oracle data base

Remove LOG.* from the SELECT; UNIQUE (as well as DISTINCT) is applied to all columns you select, not only to the one you put into brackets.
[EDIT]
Scott's EMP table contains employees that work in different departments. List of distinct departments is:
SQL> select distinct deptno from emp;
DEPTNO
----------
30
20
10
SQL>
If you include additional columns, such as JOB, the list is changed to
SQL> select distinct deptno, job from emp order by deptno, job;
DEPTNO JOB
---------- ---------
10 CLERK
10 MANAGER
10 PRESIDENT
20 ANALYST
20 CLERK
20 MANAGER
30 CLERK
30 MANAGER
30 SALESMAN
9 rows selected.
SQL>
It is now distinct per DEPTNO and per JOB; you can't get only distinct DEPTNO in such a query.
[EDIT #2: aggregation]
If "distinct" means distinct DEPTNO and the first job for that DEPTNO, then you might need this:
SQL> select deptno, min(job) first_job from emp
2 group by deptno
3 order by deptno;
DEPTNO FIRST_JOB
---------- ---------
10 CLERK
20 ANALYST
30 CLERK
SQL>
[EDIT #3, example based on your query]
Select t.id,
min(log.id) log_id,
min(log.time) log_time,
<the rest of LOG table columns goes here, all of them with MIN>
from tableA log
inner join table ...
<the rest of your query goes here>
group by t.id;

How about something like this?
Select t.id, log.*
from tableA log inner join
(select t.*, row_number() over (partition by id1 order by id) as seqnum
from tableT t
) t
on t.id1 = log.id1
where log.time >= (somedate) and
log.time < (somedate) and
t.seqnum = 1
ref_id = 20 and ref_id = 30 -- this is ALWAYS false, but I'm ignoring that
Notes:
I have no idea what the subquery is supposed to be doing.
The conditions on ref_id will always evaluate to FALSE, so that logic is almost certainly not what you intend.
If ref_id is in the transaction table, then the conditions should be moved to the subquery.

Related

SELECT STATEMENT WITH ORDER BY

I have a simple select statement with joins in oracle I have one agregate function like sum(COLUMN) , my query works fine and it return the result , Now I am adding one-two more columns from same table to which I have a join , I am requiring simple column values no agregate function when I add first column it ask me that it needed to be in group by as it is not agregate function I did that , but after doing that i am getting more number of rows which i were getting previously what could be the reason, when I add one more columns than again number of rows increased like with my first query without adding these two columns the result was 544 and now it is 766
select distinct 'carTypes' as type, mi.WOMENNAME as "mother name", mi.womencnic as "mother CNIC", '' as BFORMNO, '' as child_gender, mi.PROVINCE, mi.district, mi.tehsil, mi.HUSBANDNAME, mi.PHONENO contact, mi.address, SUM(p.amount) paid_amount
from MINFORMATION mi
inner join PAYMENTINFORMATION p on p.BENEFICIARYID=mi.WOMENID and p.BANKSTATUS='Successfull'
where mi.month IS NOT NULL
and p.generationdate between '24-JUN-21' and '01-JAN-22'
group by mi.WOMENNAME, mi.womencnic,mi.PROVINCE, mi.district, mi.tehsil, mi.HUSBANDNAME, mi.PHONENO , mi.address
above is my query
That's how it goes. When there's an aggregate function in the select column list all non-aggregated columns must be included in the group by clause (group by, not order by as your title suggests; order by is irrelevant in this matter).
For example, as of Scott's emp table: if you want to compute sum of salaries, the result is only one row:
SQL> select sum(sal)
2 from emp;
SUM(SAL)
----------
29025
If you add deptno column, it means you want to compute sum of salaries per each department. As there are employees from 3 departments, it results in 3 rows:
SQL> select deptno, sum(sal)
2 from emp
3 group by deptno;
DEPTNO SUM(SAL)
---------- ----------
30 9400
20 10875
10 8750
Adding yet another column - job - means that you want to calculate sum of salaries per each department, and per each job within that department; all that increases number of resulting rows:
SQL> select deptno, job, sum(sal)
2 from emp
3 group by deptno, job
4 order by deptno, job;
DEPTNO JOB SUM(SAL)
---------- --------- ----------
10 CLERK 1300
10 MANAGER 2450
10 PRESIDENT 5000
20 ANALYST 6000
20 CLERK 1900
20 MANAGER 2975
30 CLERK 950
30 MANAGER 2850
30 SALESMAN 5600
9 rows selected.
Therefore, what kind of output would you want to get? If you could explain it, maybe we could suggest approach that would make it happen.

What is mean the condition COUNT(1) = 1 in oracle sql

I have two table and write select:
SELECT A.code, B.account, A.ano
FROM atable A, dtable B
where A.ano=B.dno
group by A.code, B.account, A.ano
having count(1)=1;
if I add condition having count(1)=1 I didn't get any result, why?
Query groups data per columns listed in the GROUP BY clause. HAVING restricts result set to those whose count (for those grouped columns) equals 1.
If query returns nothing, it means that there's not at least one combination of those columns that has only one row as a result.
For example (based on Scott's EMP table):
SQL> select job, count(*) from emp
2 group by job;
JOB COUNT(*)
--------- ----------
CLERK 4
SALESMAN 4
PRESIDENT 1 --> only one person is a president
MANAGER 3
ANALYST 2
Your query:
SQL> select job
2 from emp
3 group by job
4 having count(*) = 1;
JOB
---------
PRESIDENT
Let's set someone else to be a president:
SQL> update emp set job = 'PRESIDENT' where ename = 'ADAMS';
1 row updated.
The query doesn't return anything now (as there are 2 presidents):
SQL> select job
2 from emp
3 group by job
4 having count(*) = 1;
no rows selected
SQL>
As of count(1): no point in it, use count(*) instead.

can't we use select another column with max() in sql

I have a table emp (ename,eid,did,sal,sex) where column did is foreign key with another table dept (did,dname).
I want to get the max sal of the company along with name and did of the person who is getting it.
I am executing following query
select did,ename ,max(sal) from emp;
But the Result is :
ORA-00937: not a single-group group function
so My question is can't I have more than 1 columns ?
You can't use MAX aggregate function like this. Using MAX without a GROUP BY clause will just return one record with the maximum sal value. You are not allowed to place any more non-aggregated fields in the SELECT clause.
If you want to get the record having the maximum sal value, then you have to do a self-join:
select e1.*
from emp as e1
inner join (
select max(sal) as max_sal
from emp
) as e2 on e1.sal = e2.max_sal
Note: The above query will return more than one records from table emp, in case more than one records share the same maximum sal value.
Edit:
If you want to get the maximum salary per department then you have to include a GROUP BY clause in the derived table used:
select e1.*
from emp as e1
inner join (
select did, max(sal) as max_sal
from emp
group by did
) as e2 on e1.did = e2.did and e1.sal = e2.max_sal
You would have to group the results by the sal column:
select did,ename,max(sal) from emp group by sal
MAX operates over the group specified in a GROUP BY clause and finds the maximum value for each group. When not specifying a set of columns to group by, it finds the max for the entire results set.
You need to find the max sal, then you can query the rows that match:
select did, ename, sal
from emp
where sal = (select max(sal) from emp)

why "ANY" isn't working properly?

I'm learning SQL using Oracle 10g. I need a query that returns the department with the most employees to use it in a update sentence. I already solved it, but I couldn't figure out why this query won't work:
select deptno
from (select deptno,
count(*) num
from emp
group by deptno)
where not num < any(select count(deptno)
from emp
group by deptno)
It puzzles me more since according to the documentation it should be equivalent and optimized into the following:
select deptno
from (select deptno,
count(*) num
from emp
group by deptno )
where not exists( select deptno,
count(*)
from emp
having count(*) > num
group by deptno)
That one works without errors. The following also work:
select deptno
from (select deptno,
count(*) num
from emp
group by deptno)
where num = (select max(alias)
from (select count(deptno) alias
from emp
group by deptno))
select deptno
from emp
group by deptno
having not count(deptno) < any( select count(deptno)
from emp
group by deptno)
Edit. Probably it'll help if I post the return values of the inner selects.
The first select returns:
Dept. Number Employees
30 6
20 5
10 3
The last one returns (3,5,6)
I checked them individually. It's also weird that if I put the values manually it works as expected and will return 30 as the department with most employees.
select deptno
from (select deptno,
count(*) num
from emp
group by deptno)
where not num < any(6,5,3)
I'm using Oracle 10g 10.2.0.1.0
Last edit, probably. Still don't know what's happening, but the behaviour is as if the last select is returning null somehow. So, even if I remove the ´not´, it still doesn't select anything.
If someone is interested I also found this useful:
TSQL - SOME | ANY why are they same with different names?
Read the first answer. It's probably better to avoid the use of any/some, all.
Here's a similar example which may clarify things (Standard SQL, can be easily transformed for Oracle):
WITH T
AS
(
SELECT *
FROM (
VALUES (0),
(1),
(2),
(NULL)
) AS T (c)
)
SELECT DISTINCT c
FROM T
WHERE 1 > ALL (SELECT c FROM T T2);
This returns the empty set, which is reasonable: given the presence of the null in the table, 1 > NULL is UNKNOWN, therefore it is not known whether the value 1 is greater than all values in the set.
However, adding the NOT operator:
WHERE NOT 1 > ALL (SELECT c FROM T T2);
returns all values in the set, including the null value. At first glance this seems wrong: given that 1 > 2 is FALSE we can say with certainty that the value 1 is not greater than all values in the set, regardless of the null.
However, in this case the NOT is simply flipping the earlier result i.e. the opposite of all no rows is all rows! ;)
Further consider the negated comparison using a column (rather than the literal value 1):
WHERE NOT c > ALL (SELECT c FROM T T2);
This time it returns all rows except for the null value.
Correction (update)
not num < any(select ...)
should be the same as your other queries. You can also try this variation:
num >= ALL(select ...)
but I can't understand why yours is giving wrong results. Perhaps because of the not precedence. Can you trythis instead?:
not ( num < ANY(select ...) )
Full queries:
select deptno
from (select deptno, count(*) num from emp group by deptno)
where num >= all(select count(deptno) from emp group by deptno)
and:
select deptno
from (select deptno, count(*) num from emp group by deptno)
where not ( num < any(select count(deptno) from emp group by deptno) )

Can you use multiple columns for a not in query?

I recently saw someone post this as part of an answer to an SO query question:
SELECT DISTINCT a, b, c
FROM t1
WHERE (a,b,c) NOT IN
( SELECT DISTINCT a,b,c FROM t2 )
I'm a bit confused, as I always thought that you can't use multiple columns for "NOT IN" ("where(a,b,c)", etc.). Is this correct SQL syntax? And how about MySQL?
Googling it suggests that it will work on some databases but not others. You can use this instead:
SELECT DISTINCT a, b, c
FROM t1
WHERE NOT EXISTS
(SELECT 1 FROM t2
WHERE t1.a = t2.a AND t1.b = t2.b AND t1.c = t2.c)
It's a SQL extension. Oracle, PostgreSQL and MySQL have it. SQL Server 2005 does not have it. I'm not sure about others.
It certainly does work in Oracle. Quick contrived example:
SQL> select ename, job, deptno from emp
2 where (ename, deptno) in
3 ( select ename, deptno from emp
4 where job = 'MANAGER'
5 );
ENAME JOB DEPTNO
---------- --------- ----------
JONES MANAGER 20
CLARK MANAGER 10
PARAG MANAGER 30
This also works:
SQL> select ename, job, deptno from emp
2 where (ename, deptno) in (('JONES',20),('CLARK',10));
ENAME JOB DEPTNO
---------- --------- ----------
JONES MANAGER 20
CLARK MANAGER 10
NOT IN too:
SQL> select ename, job, deptno from emp
2 where (ename, deptno) not in
3 ( select ename, deptno from emp
4 where job = 'MANAGER'
5 );
ENAME JOB DEPTNO
---------- --------- ----------
SMITH CLEANER 99
SCOTT ANALYST 20
KING PRESIDENT 10
FORD ANALYST 20
MILLER CLERK 10
Not that I'm aware of, but if thy're character type (or can be converted to char types), you can fake it:
SELECT DISTINCT a, b, c
FROM t1
WHERE a+b+c NOT IN
( SELECT DISTINCT a+b+c FROM t2 )
Try this
SELECT DISTINCT a, b, c
FROM t1,
(SELECT DISTINCT a,b,c FROM t2) as tt
WHERE t1.a NOT IN tt.a
AND t1.b NOT IN tt.b
AND t1.c NOT IN tt.c
Note: This has not been tested, it hasn't even been proven correct.
Others have already answered the question, but as a performance suggestion, if you're dealing with data of any significant size always use the EXISTS statement rather than IN. It will be faster in almost every case.
http://decipherinfosys.wordpress.com/2007/01/21/32/