SQL AVG and overall average of departments - sql

my data is like this
Dept Sub_Dept Sal
d1 sd1 100
d1 sd1 150
d1 sd2 100
d1 sd2 200
d1 sd2 350
d2 sd1 100
d2 sd1 250
d2 sd1 250
d2 sd2 200
d2 sd2 350
My output should be the count of each sub dept, the AVG of the Sal values of each sub department (sub_dept), and the AVG of all departments (dept)
I want my output to look like this
Result
d1 sd1 2 125
d1 sd2 3 200
Total 5 180
d2 sd1 3 200
d2 sd2 2 225
Total 5 230
grand total 10 205
How to get the inner and outer AVG values ?

use union all
select dept,sub_dept,count(*) cnt ,avg(Sal) as av
from table_name group by dept,sub
union all
select 'total','', count(*),avg(Sal)
from table_name

Most dialects of SQL support the standard grouping sets (or at least roll up). Typical syntax would be:
select dept, sub_dept, avg(sal)
from t
group by grouping sets ( (dept, sub_dept), () );

Related

PostgreSQL: How do I join same table multiple times and take data?

The table I have is this:
C1
C2
userid
1
50
100
2
40
101
3
30
102
4
20
103
5
10
104
I need the userid and count() userid WHERE (Condition satisfied)
by input
userid IN (100,101,102,103,104,105)
The condition is :
C1 > (input userid's C1) and C2 < (input userid's C2)
I need it like this :
userid
Count
100
4
101
3
102
2
103
1
Join and aggregate as the following:
SELECT D.userid, COUNT(*) cnt
FROM table_name T JOIN table_name D
ON T.C1 > D.C1 AND T.C2 < D.C2
WHERE D.userid IN (100,101,102,103,104,105)
GROUP BY D.userid
ORDER BY D.userid
See a demo.

Get only latest records of each ID in PostgreSQL

I have two tables
accounts table
account_id location_id
1 11
1 12
2 21
2 22
Events_table
location_id events_id event_date
11 e1 2022/03/04
11 e3 2022/03/05
12 e2 2022/03/10
21 e5 2022/04/10
21 e2 2022/04/09
The result I expected is to get only latest event_id for location with respect to account
Result Expected:
account_id location_id events_id event_date
1 11 e3 2022/03/05
1 12 e2 2022/03/10
2 21 e5 2022/04/10
Use:
with cte as
( select *,
row_number() over(partition by location_id order by event_date desc ) row_num
from Events
) select a.account_id,
a.location_id,
cte.events_id,
cte.event_date
from accounts a
inner join cte on cte.location_id=a.location_id
where cte.row_num=1;
Demo

How to SUM many rows into 1 row in SQL Server?

The following is my syntax
with AA as
(
select distinct Store_Code, sum([Transactions]) as totaltrans
from CRM_RETAIL_SUMMARY
where Store_Code in ('L43','J62','L45','UA2','A35','949','C50','L44','Y45')
and Trans_Hdr_Sale_Date BETWEEN '2018-12-1' AND '2018-12-31'
group by Transactions, Store_Code
),
BB as
(
select distinct[Store_Code] as storecode from CRM_RETAIL_SUMMARY
)
select AA.totaltrans, BB.storecode
from AA
inner join BB on AA.Store_Code = BB.storecode
and then the result shows this:
storecode totaltrans
----------------------
A35 65
A35 76
A35 48
A35 62
A35 56
UA2 5
UA2 6
UA2 8
UA2 15
UA2 9
UA2 16
949 16
949 29
949 55
But I want to SUM each of the storecode like the following but I don't know how:
storecode totaltrans
---------------------
A35 307
UA2 59
Thank you for all answers
You only need to group by store_code, not store_code, transactions. and you don't need the 2nd cte.
with AA as (
select Store_Code, sum([Transactions]) as totaltrans
from CRM_RETAIL_SUMMARY
where Store_Code in ('L43','J62','L45','UA2','A35','949','C50','L44','Y45')
and Trans_Hdr_Sale_Date BETWEEN '2018-12-1' AND '2018-12-31'
group by Store_Code
)
select * from AA;
Would you just use group by?
select BB.storecode, sum(AA.totaltrans)
from AA join
BB
on AA.Store_Code = BB.storecode
group by BB.storecode;
Of course, this goes after the CTEs.

Query for get the specific record

Hi i have a table in which records as follows,every item have some variants and their quantity. i want to fetch only those item's record in which at least 3 variants value exist. ( a items have some qty in 3 variants but b have quantity only 2 variants, so i need only those record who have values at least in 3 records)
a 80 2
a 85 3
a 90 4
b 85 2
b 90 1
c 80 34
c 85 45
c 90 56
c 95 67
d 80 5
d 85 3
d 90 124
d 95 23
d 100 98
e 95 4
f 80 3
f 85 232
f 90 2
f 95 3
f 100 34
Result should be:
a 80 2
a 85 3
a 90 4
c 80 34
c 85 45
c 90 56
c 95 67
d 80 5
d 85 3
d 90 124
d 95 23
d 100 98
f 80 3
f 85 232
f 90 2
f 95 3
f 100 34
You can try with left join/is not null:
select t1.*
from tbl t1
left join ( select item
from tbl
group by item
having count(item) >= 3) t2 on t1.item = t2.item
where t2.item is not null
or in:
select t1.*
from tbl t1
where t1.item in ( select item
from tbl
group by item
having count(item) >= 3)
or exists:
select t1.*
from tbl t1
where exist ( select *
from tbl
where item = t1.item
group by item
having count(item) >= 3)
select * from a t1 where (select count(*) from a t2 where t2.x=t1.x)>2;
a is the table name, x is the first column's name.

Oracle 10 g -SQL

How to find top 2 salaries in each department in emp table?
Emp Table
-----------
Row_id Salary Dept
R1 2000 D1
R2 3000 D1
R3 4000 D1
R4 5000 D1
R5 2000 D2
R6 3000 D2
R7 4000 D2
R8 5000 D2
select
row_id,salary,dept
from
(
select
row_number() over (partition by dept order by salary desc) as sno,
row_id,salary,dept
from emp
) t
where sno<=2
please try this
select T1.Dept,T2.Salary
from Emp_Table T1 join Emp_Table T2
on T1.Dept=T2.Dept
and T1.Salary>=T2.Salary
group by T1.Dept,T2.Salary
having COUNT(*) <=2