What is mean the condition COUNT(1) = 1 in oracle sql - 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.

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.

How to intersect 5 sql queries that do not belong to same table and have millions of data as output for each query

How to intersect 5 SQL queries that do not belong to same table and have millions of data as output for each query?
I want to find out data that is present in all the five queries output.
You can intersect them, as you said (all statements have to have equal number of columns and they have to match in datatype), e.g.
SQL> select empno, ename from emp
2 intersect
3 select deptno, loc from dept;
no rows selected
SQL>
Or, you can use each query as a CTE and then join them (result will return rows that match):
SQL> with
2 q1 (valn, valc) as
3 (select empno, ename from emp),
4 q2 (valn, valc) as
5 (select deptno, loc from dept)
6 --
7 select a.valn
8 from q1 a join q2 b on a.valn = b.valn and a.valc = b.valc;
no rows selected
SQL>
Millions of rows? It'll probably take time to get the result, I presume.

sql Group by does not work on selecting multiple columns

I have following query
SELECT ACTIONFINANCIALTRANSACTIONLOG.ID_CSE,
ACTIONFINANCIALTRANSACTIONLOG.DTE_PROC
FROM CSESDEV02.FINANCIAL_TRAN_LOG ACTIONFINANCIALTRANSACTIONLOG
GROUP BY ACTIONFINANCIALTRANSACTIONLOG.ID_CSE
HAVING COUNT(TXT_DESC) > 9
this results in
ORA-00979: not a GROUP BY expression
00979. 00000 - "not a GROUP BY expression"
*Cause:
*Action: Error at Line: 57 Column: 47
however, if i select only 1 column , it works
SELECT ACTIONFINANCIALTRANSACTIONLOG.ID_CSE
FROM CSESDEV02.FINANCIAL_TRAN_LOG ACTIONFINANCIALTRANSACTIONLOG
GROUP BY ACTIONFINANCIALTRANSACTIONLOG.ID_CSE
HAVING COUNT(TXT_DESC) > 9
why is that?
Although there's no aggregate function in SELECT column list, all columns that aren't aggregated should be part of the group by clause.
If there are 2 columns you're selecting, both have to be part of the group by.
BTW, table alias should be short so that it "simplifies" query and makes it easier to read. You did the opposite.
This is what works OK - only one column in select and it is part of group by:
SQL> select deptno
2 from emp
3 group by deptno
4 having count(job) > 1;
DEPTNO
----------
30
20
10
This doesn't work: two columns in select list, only one in group by:
SQL> select deptno,
2 ename
3 from emp
4 group by deptno
5 having count(job) > 1;
ename
*
ERROR at line 2:
ORA-00979: not a GROUP BY expression
But, when they both are in group by, query is OK:
SQL> select deptno,
2 ename
3 from emp
4 group by deptno, ename
5 having count(job) > 1;
no rows selected
SQL>
Read documentation.
Gist:
SelectItems in the SelectExpression with a GROUP BY clause must
contain only aggregates or grouping columns.
This is happening because GROUP by require all the column defined in SELECT clause.
The SELECT statement used in the GROUP BY clause can only be used contain column names, aggregate functions, constants and expressions.
select count(1),deptno
from emp
group by deptno
having count(1) > 1;
ACTIONFINANCIALTRANSACTIONLOG.DTE_PROC is not the product of a summary function and is not mentioned in the GROUP_BY clause so you get the error you've gotten. Perhaps you could use:
SELECT ftl.ID_CSE,
ftl.DTE_PROC
FROM (SELECT af.ID_CSE,
COUNT(af.TXT_DESC) AS TXT_DESC_COUNT
FROM CSESDEV02.FINANCIAL_TRAN_LOG af
GROUP BY af.ID_CSE
WHERE COUNT(af.TXT_DESC) > 9) iq
INNER JOIN CSESDEV02.FINANCIAL_TRAN_LOG ftl
ON ftl.ID_CSE = iq.ID_CSE
Syntax aside, think about the aggregation group you are defining with your group by clause:
GROUP BY ID_CSE
means you want one row per ID_CSE. Examples would be average salary per department, total sales per region, vaccinations per country.
In that one row for each id_cse, what dte_proc should be displayed if there is more than one distinct value?
For example, say your data contains
ID_CSE DTE_PROC
------ ----------
1 X
1 Y
2 Z
Now if you query
select id_cse, date_proc, count(*) from financial_tran_log
group by id_cse
what results do you expect to see?
ID_CSE DTE_PROC COUNT(*)
------ -------- --------
1 ??? 2
2 Z 1
It can't be done, hence the syntax error.

If count(column) Then Select in Oracle

can I do something like this in oracle?
I want to check if the result dataset is more than 20k records then DO NOT SELECT, if less than 20k then SELECT.
DECLARE cnt number;
BEGIN
select count(*) into cnt from ir_mpn where material LIKE '%A00%';
IF cnt > 20000 THEN
select manuf_part, material, vendor, vendor_name from ir_mpn where material LIKE '%A00%';
END IF;
END;
I tried to do like this but shows error:
ORA-06550: line 6, column 4:
PLS-00428: an INTO clause is expected in this SELECT statement
Any better suggestions for me to do this?
This is PL/SQL so your SELECT statement requires an INTO clause. As you're about to return thousands of rows, you can't return them into scalar variables but e.g. collection or ref cursor.
However, if you want to do it in SQL, then see if this helps; example is based on Scott's DEPT table:
SQL> select * from dept;
DEPTNO DNAME LOC
---------- -------------------- --------------------
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON
I'd want to select rows from it if number of rows is less than 3; as number of rows is 4, nothing is returned:
SQL> select * from dept
2 where 3 >= (select count(*) from dept);
no rows selected
How about 5 rows?
SQL> select * from dept
2 where 5 >= (select count(*) from dept);
DEPTNO DNAME LOC
---------- -------------------- --------------------
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON
SQL>
In your case:
select manuf_part, material, vendor, vendor_name
from ir_mpn
where material LIKE '%A00%'
and 20000 >= (select count(*)
from ir_mpn
where material like '%A00%'
);
Yes. Depends on what do you like to achieve.
In PL/SQL you cannot use plain SELECT to return rows.
Some options are to use INTO (like you did for COUNT()) or use cursor (like below).
The simple approach is:
for r_material in (select manuf_part, material, vendor, vendor_name from ir_mpn where material LIKE '%A00%') loop
-- process each r_material record here f.e.
-- if r_material.vendor = 'ORACLE' then...
end loop;

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

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.