Student, Department Order by both with condition - sql-server

I am stuck in a query, my query is as follow:
SELECT department_name AS 'Department Name', COUNT(*) AS 'No of Employees' FROM departments INNER JOIN employees ON employees.department_id = departments.department_id GROUP BY departments.department_id, department_name
ORDER BY COUNT(*) DESC;
this query is giving me results as in below attachment
What i want now is to sort the departments alphabetically if two or more department have same number of students. e.g "Purchasing" and "Finance" should be sort alphabetically.
You can try this query in the following link:
Check your query here

This is simple. You can order by your result set by multiple columns as follows:
SELECT department_name AS 'Department Name', COUNT(*) AS 'No of Employees'
FROM departments INNER JOIN employees ON
employees.department_id = departments.department_id
GROUP BY departments.department_id, department_name
ORDER BY COUNT(*) DESC, department_name Asc;
The following thread is a good read
SQL Multiple Column Ordering
Hope this helps :)

Is this what you are looking for.?
SELECT department_name AS 'Department Name', COUNT(*) AS 'No of Employees'
FROM departments INNER JOIN employees ON employees.department_id = departments.department_id GROUP BY departments.department_id, department_name
ORDER BY department_name,COUNT(*) DESC;

Related

List customers who sold most in mssql

I'm new to sql.
I have to select top 3 companies who have the highest sells
Company Table:
CompanyId, Compnayname,etc
Orders Table:
OrderId, companyId,price,etc
select top 3 companyname , (select sum(price) from ordes) as Maximum from company order by Maximum Desc?
I think i need to join these but i cant find a way around it
Join these tables, group by company's name and order by their total sales:
select top 3 c.Companyname, sum(o.price) as TotalSales
from Orders o
inner join Company c on c.CompanyId = o.companyid
group by c.Companyname
order by TotalSales desc

Subtracting two columns within the sql query

I have been trying to subtract two columns in sql server to form a third one. Below is my query
select AD.Id, Sum(APS.Amount) AS TotalDue,
isnull((select sum(Amount) from Activation where InvoiceId in (select InvoiceId from Invoices where AgreementId = AD.Id)),0)
As AllocatedToDate
from AdvantageDetails AD
inner join AllPaymentsSubstantial APS
on APS.AgreementId=AD.Id
where AD.OrganizationId=30
group by AD.Id
What I tried is below but it is not working. :
select AD.Id, Sum(APS.Amount) AS TotalDue,
isnull((select sum(Amount) from Activation where InvoiceId in (select InvoiceId from Invoices where AgreementId = AD.Id)),0)
As AllocatedToDate , (TotalDue-AllocatedToDate) as NewColumn
from AdvantageDetails AD
inner join AllPaymentsSubstantial APS
on APS.AgreementId=AD.Id
where AD.OrganizationId=30
group by AD.Id
At last I tried it using a CTE which worked fine. But I want to do it without creating CTE. Can there be any other way for performing the same functionality. I do not want to use CTE because it is forcasted that there
can be other columns which will be calculated in future.
with CTE as(select AD.Id, Sum(APS.Amount) AS TotalDue,
isnull((select sum(Amount) from Activation where InvoiceId in (select InvoiceId from Invoices where AgreementId = AD.Id)),0)
As AllocatedToDate , (TotalDue-AllocatedToDate) as NewColumn
from AdvantageDetails AD
inner join AllPaymentsSubstantial APS
on APS.AgreementId=AD.Id
where AD.OrganizationId=30
group by AD.Id) select * , (CTE.TotalDue-CTE.AllocatedToDate)As Newcolumn from CTE
You can do it without a CTE by repeating the entire formula that makes up AllocatedToDate.
You cannot use the alias of a column in the SELECT list, so you cannot do this:
SELECT {some calculation} AS ColumnA, (ColumnA - ColumnB) AS ColumnC
If you don't want to use a CTE or derived table, you have to do this:
SELECT {some calculation} AS ColumnA, ({some calculation} - ColumnB) AS ColumnC
And by the way, I can't imagine why the possibility of future columns being added is a reason not to use a CTE. To me, it sounds like a reason TO use a CTE, as you will only have to make changes in one place in the code, and not duplicate the same code in different places in the same query.
You can just use nested queries:
select Id, TotalDue, AllocatedToDate, (TotalDue-AllocatedToDate) as NewColumn
from (
select AD.Id, Sum(APS.Amount) AS TotalDue,
isnull((select sum(Amount) from Activation where InvoiceId in (select InvoiceId from Invoices where AgreementId = AD.Id)),0)
As AllocatedToDate
from AdvantageDetails AD
inner join AllPaymentsSubstantial APS
on APS.AgreementId=AD.Id
where AD.OrganizationId=30
group by AD.Id
) x

ORDER BY clause error

Hey guys I am getting this exception when trying to run the query
Column restaurantData.restaurantId is invalid in the select list
because it is not contained in either an aggregate function or the
GROUP BY clause.
Query:
SELECT
T1.restaurantId AS ID,
COUNT(T2.post_id) AS favCount
FROM
restaurantData AS T1
INNER JOIN
favoriteData AS T2 ON T1.restaurantId = T2.post_id
ORDER BY
favCount DESC, ID DESC
It says that I have to add all select columns which are not aggregated in ORDER BY clause, which I already did for restaurantID. But its still giving me error.
You are missing GROUP BY T1.restaurantId in the query.
SELECT T1.restaurantId AS ID,
COUNT(T2.post_id) AS favCount
FROM restaurantData AS T1
INNER JOIN favoriteData AS T2
ON T1.restaurantId = T2.post_id
GROUP BY T1.restaurantId
ORDER BY favCount DESC,
ID DESC
If you have no GROUP BY clause at all then this gives you an aggregate of the whole source table (in which case inclusion of restaurantId in the select list is invalid without wrapping that in an aggregate) rather than broken into groups by restaurant as you clearly desire.
You're using an aggregate function (COUNT), so you have to use a GROUP BY clause as well:
SELECT
T1.restaurantId AS ID,
COUNT(T2.post_id) AS favCount
FROM
restaurantData AS T1
INNER JOIN
favoriteData AS T2 ON T1.restaurantId = T2.post_id
GROUP BY
T1.restaurantID
ORDER BY
favCount DESC, ID DESC
Basically, with your query, you want to count the rows found - and you want the result grouped by each restaurantId - so that's what the GROUP BY clause expresses.

Need help creating a query for a non-normalized database

I've never worked with a non-normalized database before, so I'll try and explain my problem as best I can. So I have two tables:
The customers table holds all the customers information, and the orders table holds all the orders that they have placed. I haven't listed all the fields in the tables, just the ones that I need. The customer number in both tables is not the primary key, but I'm inner joining on them anyway. So the problem I'm having is that I don't know how to make a query that:
Selects all the customers with their first name, last name, and email, and also show the most recent orderdate, most recent total, and most recent ordertype. I know that I have to use a max() aggregate for the date, but that's as far as I got. Please help a noob out.
You can try:
SELECT FirstName,
LastName,
Email,
OrderDate,
OrderTotal,
OrderType
FROM Customers AS C
INNER JOIN Order AS O
ON O.CustomerNumber = C.CustomerNumber AND
O.OrderDate = (
SELECT MAX (O1.OrderDate)
FROM Order AS O1
WHERE O1.CustomerNumber = C.CustomerNumber)
)
assuming that Orders.OrderDate is unique for each CustomerNumber, does this work for you? if a single CustomerNumber has more than one entry in Order for OrderDate, you'll get each of those rows.
select c.FirstName, c.LastName, c.Email, o.OrderDate, o.OrderTotal, o.OrderType
from Customers c
join
(select CusomterNumber, max(OrderDate) as MostRecentOrderDate
from Orders
group by CustomerNumber
) mro on mro.CustomerNumber=s.CustomerNumber
join Orders o on o.OrderDate=mro.MostRecentOrdeDate and
o.CustomerNumber=mro.CustomerNumber
Try this:
SELECT
Customers.*, Orders.*
FROM
Customers
JOIN
(SELECT
Customer_Number,
MAX(Order_Date) OrderDate
FROM
Orders
GROUP BY
Customer_Number
) as Ord ON Customers.Customer_Number = Ord.Customer_Number
JOIN Order ON Orders.Customer_Number = Ord.Customer_Number
If you are doing this with SQL Server use the query designer and basically all you want to do is do a join since you have two keys that are the same one in Customer Table ->Customer Join on Order->Customer alias the Customer table as C and Orders table as O
so for example
SELECT Customer.*, Orders.*
From Customer c, Orders O INNER JOIN O where C.Customer Number = O.Customer Number
This should be enough to get you started.. if you don't want all the fields then fully qualify the names for example
SELECT C.FirstName, C.LastName, O.OrderDate, O.OrderType FROM Customer C, Orders O
WHERE C.Customer NUmber = O.Customer Number //this is another way of doing a Join when working with the where Clause.

How to put a subquery within an aggregate subquery

I am using SQL-Server 2000 and am trying to find duplicates with certain conditions. Someone here helped me earlier with the duplicate part which was great, however, I can't figure out how to filter the duplicated cases further.
I need to move the "where" statement to the subquery so that I only get contractor duplicated names as opposed to all duplicated names which is what's happening with this code (the code is first finding all duplicates and then filtering out the contractors and I'd like it to do the opposite). The problem is that I'm mixing it into an aggregate statement and it's giving me an error. I tried to put in another subquery within the subquery but it still gave me an error.
Any help is appreciated. Here's a simpler (I'm learning) version of the code:
SELECT DISTINCT(c1.contactid) as 'ContactID', c1.lastname as 'Last Name', c1.firstname as 'First Name'
FROM contacts c1 INNER JOIN (SELECT lastname, firstname FROM contacts group by lastname, firstname
HAVING count(*)>1)
dups on c1.lastname=dups.lastname and c1.firstname=dups.firstname
WHERE (c1.contractor=1)
For the example code you have given, placing the where clause between the "from contacts" and "group by lastname, firstname" should do they trick.
i think this is what you want:
SELECT
contact.ContactId,
contact.FirstName,
contact.LastName
FROM contacts as contact
INNER JOIN
(
SELECT ContactID FROM contacts GROUP BY FirstName, LastName HAVING Count(*) > 1
) AS Dups
ON Dups.ContactId = contact.ContactId
WHERE
contact.isContractor = 1
you are very close. this will provide you a list of each individual record that has a matching record with the same first name and last name. Hope this helps
Select C.contactid As ContactID
, C.LastName As [Last Name]
, C.FirstName As [First Name]
From contacts C
Inner Join (
Select C1.LastName, C1.FirstName
From contacts As C1
Where C1.contractor = 1
Group By C1.LastName, C1.FirstName
Having Count(*) > 1
) As dups
On C.LastName = dups.LastName
And C.FirstName = dups.FirstName
Where C.contractor = 1
You are going to need the filter on contractor = 1 in both the subquery and the outer query. Otherwise, you might return people that happen to have the same name as a contractor and are duplicated.
Also, you do not need the Distinct keyword if ContactId is the primary key of the Contacts table.
Move the where clause to the subquery. It fill first filter out all non-contractors, and then group the remainder.
SELECT DISTINCT
c1.ContactId
,c1.lastname as 'Last Name'
,c1.firstname as 'First Name'
from contacts c1
inner join (select lastname, firstname
from contacts
where c1.contractor = 1
group by lastname, firstname
having count(*) > 1) dups
on c1.lastname = dups.lastname
and c1.firstname = dups.firstname
Oh, and unless there's a really good reason, you really don't want to include embedded spaces in your column aliases ("Last Name", "First Name").

Resources