Count without nested select: is this possible? - sql

Database:
Department Position Points
A Manager 50
A Supervisor 10
A Supervisor 10
A Staff 2
A Staff 2
B Manager 40
B SuperVisor 8
B Staff 2
B Staff 2
B Staff 2
Desired query result:
Dept Manager Count Supervisor Count Staff Count Staff Total Pts
A 1 2 2 4
B 1 1 3 4
Is the desired query result possible without using nested select with count?
We have a certain stored procedure similar to this using nested counts and we like to make it simpler and perform better/faster

Use Conditional Aggregate to count only the specific data
Select Department,
count(case when Position = 'Manager' then 1 END) as Manager,
count(case when Position = 'Supervisor' then 1 END) as Supervisor,
count(case when Position = 'Staff' then 1 END) as Staff
From yourtable
Group by Department
If you are using Sql Server use this
SELECT Department,
Manager,
Supervisor,
Staff
FROM Yourtable
PIVOT (Count(Position)
FOR Position IN (Manager,Supervisor,Staff))pv

Use conditional SUM:
SELECT Department,
SUM(CASE WHEN Position = 'Manager' THEN 1 END) as Manager,
SUM(CASE WHEN Position = 'Supervisor' THEN 1 END) as Supervisor,
SUM(CASE WHEN Position = 'Staff' THEN 1 END) as Staff
FROM yourtable
GROUP BY Department

Or You can use PIVOT operator:
select Detartment, Manager, Supervisor, Staff
from yourtable
pivot (count(Position) for Position in (Manager, Supervisor, Staff)) Result

Related

SQL Group by on multiple conditions on same table

enter image description hereI am trying to write an SQL query to get below output.
table has below data:
ID GENDER
10 M
10 F
10 F
20 F
20 M
Output:
ID Male Female
10 1 2
20 1 1
do i need to use case with group by. Can someone help here.
use simple group
select id,sum(case when GENDER = 'M' then 1 else 0 end) as Male,
sum(case when GENDER = 'F' then 1 else 0 end) as FeMale
from tablename
group by id

Creating separate columns based on the main column in a sql table.?

I have a table with thousands of record which has a structure like below :
Street
House
Persons
1
A
2
1
B
5
1
C
3
2
D
6
2
E
9
3
F
4
I want to frame a sql query such that its output will be like:
Street
House
Persons
House
Persons
House
Persons
1
A
2
B
5
C
3
2
D
6
E
9
null
null
3
F
4
null
null
null
null
The number of house in a street is not the same for all the streets and it varies based on the street.
Can someone please help me in framing this query? Thanks!
For a fixed maximum number of rows per street, you can use window functions and aggregation:
select street,
max(case when rn = 1 then house end) as house1,
max(case when rn = 1 then persons end) as persons1,
max(case when rn = 2 then house end) as house2,
max(case when rn = 2 then persons end) as persons2
from (
select t.*,
row_number() over(partition by street order by house) rn
from mytable t
) t
group by street
You can add more conditional expressions to the select clause to handle more rows per street.

Oracle SQL: Obtain count of distinct column values based on another column

Here is a sample data to explain my case,
CompanyInfo:
Name, Company, Location, Completed, Pending
Andy AA Home 4 2
Jim AA Office 3 3
Dahli AA Home 4 2
Monica AA Home 4 2
Chandler AA Home-Office 1 0
Ashley AA Home-Office 1 0
The last three columns have duplicated information and I am trying to obtain count of location, completed and pending which are bound to each other. So the output would look something like below,
Company, Count(Locations), Count( Completed+Pending > 0),
AA 3 3
Why Count( Completed+Pending > 0) is 3? there are just three unique combinations of Home, Office and home-office columns where sum of completed+pending is > 0.
I did try below, but it gives me (AA, 3, 6) since it is processing all the 6 rows to obtain the count.
select Company,
count(distinct Location),
SUM (
CASE
WHEN (Completed + Pending) > 0 THEN 1
ELSE 0
END)
AS Total
From CompanyInfo
group by Company;
Any pointers?
I think you want a conditional count(distinct):
select Company,
count(distinct Location),
count(distinct case when Completed + Pending > 0 then location end)
from CompanyInfo
group by Company;

Sort by aggregate value in sql

Let's say I have the following student data:
classroom gender student_id
-------------------------------------
First Grade M 123
First Grade F 124
First Grade F 125
Second Grade M 126
Third Grade M 127
...
I want to produce the following result: top 3 biggest classrooms ordered by total number of students with detail for each:
classroom boys_count girls_count total_count
--------------------------------------------------
Third Grade 30 30 60
First Grade 20 5 25
Fourth Grade 10 10 20
How can I do that in sql ? If necessary, I can use specific postrges features.
What I tried so far:
SELECT count(*) as total_count
, gender
, classroom
ORDER BY 1
GROUP BY classroom, gender
LIMIT 3
Then I re-organise results in some scripting language. But this is too slow. I want to have the correct results with one query
select classroom as name,
sum(case when gender = 'M' then 1 else 0 end) as boys_count,
sum(case when gender = 'F' then 1 else 0 end) as girls_count,
count(*) as total_count
from your_table
group by classroom
order by count(*) desc
limit 3

Sql Grouping Query

I'm wondering how i can get a query to put these groupings into one line so i can put it into a vb.net datagrid.
For example Number, Company Name, Current, 31-60, 61-90
Which would be for example company A, but get the grouping to all be on one line.
104680777, Company A, 643546.344, 34534534.77, 3454.55
To even get this query below. I had to do this.
select sum(Amount), DunsNum, CompanyName, Age
from tblARAged
group by DunsNum, Age, CompanyName
Amount Num CompanyName Age
63546.344 104680777 Company a 1
34534534.77 104680777 Company a 2
3454.55 104680777 Company a 3
3453453.66 186830733 Company b 1
345342.45 186830733 Company b 2
4542.55 186830733 Company c 3
3434.55 26409797 Company c 1
345345 26409797 Company c 2
The 1 correlates to current, 2 correlates to 31-60 and 3 correlates to 61-90 for age
I would do what Nimesh stated, though I would make a few tweaks. You want to do aggregation as late as possible:
SELECT DunsNum ,
CompanyName ,
SUM(CASE WHEN ( Age = 1 ) THEN Amt
ELSE 0
END) AS [Amount_Cur] ,
SUM(CASE WHEN ( Age = 2 ) THEN Amt
ELSE 0
END) AS [Amount_31-60] ,
SUM(CASE WHEN ( Age = 3 ) THEN Amt
ELSE 0
END) AS [Amount_61-90]
FROM tblARAged
GROUP BY DunsNum ,
CompanyName;
I haven't tested this code