SELECT STATEMENT WITH ORDER BY - sql

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.

Related

Find span of control from an employee table using SQL

I have the following table:
EMPNO
ENAME
JOB
MGR
HIREDATE
SAL
COMM
DEPTNO
7698
BLAKE
MANAGER
7839
05/01/1981
2850
-
30
7839
KING
PRESIDENT
-
11/17/1981
5000
-
10
7782
CLARK
MANAGER
7839
06/09/1981
2450
-
10
What is a query that will return span of control, or the number of people reporting to each manager, given that the same 4-digit numbers appear in both the EMPNO, as well as the MGR columns?
If possible, I'd like to know how to get the result using both a subquery and/or a self join.
I used the following query:
SELECT e.ename, m.ename
from emp e, emp m
WHERE e.empno = m.mgr
It results in a table that lists the names of each employee that correspond to each manager. Now, I just need to count the results and return a single number of employees grouped by each manager. I've tired to nest the above query in a general query using the COUNT function, but can't get it to work. A sample output of what I'd like to see is as follows:
(manager)ENAME
(direct reports)COUNT_OF_ENAME
BLAKE
n
KING
n
CLARK
n
The following query will give you the manager id and a count of how many report to them
SELECT MGR as MID, COUNT(*) AS REPORT_COUNT
FROM emp
GROUP BY MGR
Now we need to get the manager name with a join
SELECT E.ENAME, REPORT_COUNT
FROM (
SELECT MGR as MID, COUNT(*) AS REPORT_COUNT
FROM emp
GROUP BY MGR
) X
JOIN emp E ON E.empno = x.MID

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.

Creating a one query list

List a count of the number of employees who work in either department 10 or 20, the average, minimum, and maximum employee salary in these departments, and a total of all their salaries combined (This question must be done by using one query)
MY CODE:
SELECT DEPTNO, AVG(SAL), MAX(SAL), MIN(SAL), SUM(SAL) AS TOTAL_SAL
FROM EMP
WHERE DEPTNO = 10 OR DEPTNO=20
GROUP BY DEPTNO;
Table Schema:
So add a:
count(DEPTNO) as NumberEmployeesInDept
to your select and I think you will be done.

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.

LISTAGG in ORACLE

I am trying to use LISTAGG() to fetch more than two columns.
SELECT deptname, deptno, LISTAGG(ename, ',') WITHIN GROUP (ORDER BY ename) AS employees
FROM emp
GROUP BY deptno;
But it is throwing this error:
: FROM keyword not found where expected
00000 - "FROM keyword not found where expected"
*Cause:
*Action:
Error at Line: 3 Column: 12
Can please somebody explain why it is?
The LISTAGG analytic function was introduced in Oracle 11g Release 2. So, if you are on older version, you won't be able to use it.
The error seems strange. You should actually get ORA-00904: "DEPTNAME": invalid identifier as the standard EMP table in SCOTT schema doesn't have DEPTNAME column. Also, you should get ORA-00979: not a GROUP BY expression as you did not mention the SELECTed columns in the GROUP BY expression.
Using the standard EMP table in SCOTT schema:
SQL> SELECT deptno,
2 job,
3 LISTAGG(ename, ',') WITHIN GROUP (
4 ORDER BY ename) AS employees
5 FROM emp
6 GROUP BY deptno,
7 job;
DEPTNO JOB EMPLOYEES
---------- --------- ------------------------
10 CLERK MILLER
10 MANAGER CLARK
10 PRESIDENT KING
20 CLERK ADAMS,SMITH
20 ANALYST FORD,SCOTT
20 MANAGER JONES
30 CLERK JAMES
30 MANAGER BLAKE
30 SALESMAN ALLEN,MARTIN,TURNER,WARD
9 rows selected.
SQL>
Try:
SELECT deptname, deptno, LISTAGG(ename, ',') WITHIN GROUP (ORDER BY ename) AS employees
FROM emp
GROUP BY deptno,deptname;
Oracle 11g:
SELECT deptname, deptno, LISTAGG(ename, ',') WITHIN GROUP (ORDER BY deptno,job) AS employees
FROM emp
GROUP BY deptno,job;
Oracle 10g:
SELECT deptname, deptno, WMSYS.WM_CONCAT(ename) AS employees
FROM emp
GROUP BY deptno,job;