How to get multiple average values using subqueries - sql-server

There are many accountants and each of them has jobs (paid by the hour) and I need to get the accountant name of every accountant who has an average job cost higher than the overall average of job costs. How do I do this?
SELECT Accountant_Name, AVG(job_cost) as 'Average'
FROM job_view
WHERE Average > (SELECT AVG (job_cost) AS AV
FROM job_view)
GROUP BY Accountant_Name;
Everything needed is in a view named the job_view. The above code is not working any help on modifications would be appreciated. Thanks in advance.

This should do it for you:
SELECT Accountant_Name
, AVG(Job_Cost) as 'Average'
FROM Job_View
GROUP BY Accountant_Name
HAVING AVG(Job_Cost) > (SELECT AVG(Job_Cost) FROM Job_View)
As per your comment, the error you're getting at WHERE Average > is because the alias Average is not visible in a WHERE clause and usually requires you to put the entire contents of the column just as you defined it in the SELECT part.
But because in the SELECT part the Average column is a aggregate function, these can only go lower in the HAVING section, because HAVING handles filtering of aggregate conditions.
Why all this? Because there are rules for order of execution of statements in a query, as explained here.

You'll still need to Group by Accountant_Name
SELECT Accountant_Name, AVG(job_cost) as 'Average'
FROM job_view
GROUP BY Accountant_Name
Having AVG(job_cost) > (SELECT AVG (job_cost) FROM job_view);

Related

Sql Server Statement to calculate accommodation utilisation

I want to calculate the total number of Occupied accommodation as a percentage of the total accommodtion available. I am using the query below. I dont think the query is right. It returns error near From.
Please can anyone help
SELECT ((COUNT(Accommodation.dbo.House.HouseID) / COUNT(B.HouseID)) * 100) AS [Accommodation Utilisation %]
FROM (SELECT COUNT(B.HouseID)
FROM Accommodation.dbo.House B
WHERE Accommodation.dbo.House.STATUS = 'Occupied')
FROM Accommodation.dbo.House
Seems like a much easier way to do this would be to use a conditional AVG:
SELECT AVG(CASE H.STATUS WHEN 'Occupied' THEN 1. ELSE 0. END) AS Utilisation --Don't use names that need to be delimit identified.
FROM dbo.House H; --You should already be connnected to the database Accomodation, so it doesn't need to appear here
db<>fiddle

SQL Error message: Column XXX is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause

SELECT
t.[Week], MAX(t.Revenue) AS 'Max Revenue'
FROM
(SELECT
[Week], SUM([Service Total]) AS Revenue
FROM
dbo.['Data - 2017 Appmt Time$']
GROUP BY
[Week]) t;
Error:
Column 't.Week' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
What I'm trying to do is to get the max revenue and the respective week for which is that max revenue. How to make that code working? The code is working if I don't select t.[Week] in the beginning but then I get only the max revenue. If I include t.[Week] in a group by clause, as the message suggests, that I have a list of all revenues week-by-week, but I don't need it. I only need the max revenue and for which week it is.
Apologies if my question is stupid, I'm a beginner in SQL and already lost much time searching for a solution. :( Thanks a lot in advance!
You cannot use a non aggregate column in select which is not part of Group By.
Actually you don't need derived table for this, to find the week with maximum revenue use TOP 1 with Order by
SELECT top 1 [Week],
Revenue = SUM([Service Total])
FROM dbo.['Data - 2017 Appmt Time$']
GROUP BY [Week]
order by Revenue desc
As mentioned by Dan Guzman, if there is a tie in maximum revenue and you want all the tie records then replace TOP 1 with TOP 1 with Ties

SQL Server 2014 Management Studio

I'm a non profit lawyer trying to set up a SQL Server database for my agency. The issue I'm having is query based: I need a simple query that will aggregate the total number of rows on a table, not the sum of the cell contents.
I working with 4 columns of I to: attorney's name, client name, trial date and remedy (the last 2 are date and dollar amount, so integers].
*** Script for SelectTopNRows command from SSMS***
SELECT TOP 100
[attorney]
,[client]
,[trial_date]
,[remedy]
FROM [MyLegalDB]
WHERE [trial_date] between '20160101' and '20160531'
I'm trying to find a way (script, batch file, etc) that will populate a total number of cases by month (according to trial date) total number of clients, and sum the remedy column.
Sorry for the vagueness. There are privilege rules in place. Hope that helps clarify.
Thanks
Assuming that your case history spans years, not just months, try this:
SELECT
,YEAR([trial_date]) AS [Year]
,MONTH([trial_date]) AS [Month]
,COUNT(1) AS [Trial_Count]
FROM [MyLegalDB]
WHERE [trial_date] between '20160101' and '20160531'
GROUP BY YEAR([trial_date]), MONTH([trial_date])
If you want to separate this by attorney, you would need to add that column to the SELECT list, as well as the GROUP BY clause, as such:
SELECT
[attorney]
,YEAR([trial_date]) AS [Year]
,MONTH([trial_date]) AS [Month]
,COUNT(1) AS [Trial_Count]
FROM [MyLegalDB]
WHERE [trial_date] between '20160101' and '20160531'
GROUP BY [attorney], YEAR([trial_date]), MONTH([trial_date])
This is a very general answer to a very general question. If you want me to be more specific, I'm going to have to understand your goal a little better. Hope it helps.

Compute sum for distinct order numbers in ssrs report

I'm using a SQL Server 2008R2 Database and SSRS Report Builder 3.0
Trying to compute the sum of the amount owed for each order id (need to show the itemids)...but when I do, the amount owed is showing 400 (instead of 200 - line 4, 100 instead of 50 in line 7, line 9 is correct. As a result the Total line is way off)
=Sum(Fields!owe.Value)
The report is grouped by the campus.
I understand that ssrs is probably not the best place to do this computation but I don't know how to do outside of ssrs....I tried distinct and group by so far with no results.
Below is how I need the report to show like....
Thanks in advance.
Incorrect amounts are
Another example as it should display the subtotals
I would modify the SQL to produce an extra column just for purposes of summing the Owe on an OrderId. Use the Row Number to get the first item in each order, and only supply the Owe value for that item for each order:
WITH cte AS (
SELECT *,
ROW_NUMBER() OVER (PARTITION BY OrderId ORDER BY ItemId) AS rn
FROM MyTable
WHERE (whatever filters you use)
)
SELECT *,
CASE WHEN rn=1 THEN Owe ELSE 0 END AS OrderOwe
FROM cte
ORDER BY Campus, CustomerId, OrderId, ItemId
Then simply change the expression for the "Owe" textbox in your SubTotal row to this:
=Sum(Fields!OrderOwe.Value)
And you will get the sum of the Owe per order instead of per item.
Well if your owe is always the same for each item in the group you could add a Sum/Count of the item in the group which would give you the correct results in all the cases above.

Merging duplicated rows in sql table

FirstDate LastDate BaseCUR ConvertedCUR RATE
20070501 20070531 USD........EUR.................1.369748
20070601 20070615 USD........EUR.................1.354772
20070616 20070702 USD........EUR.................1.354772
20070703 20070727 USD........EUR.................1.343621
20070728 20070731 USD........EUR.................1.343621
20070801 20070831 USD........EUR.................1.376050
20070901 20071002 USD........EUR.................1.369748
Here is sample of my database, my task is to merge the 'FirstDate' and 'LastDate' of the following row(s) with the same 'RATE' into a single row.
I've tried to use ROW_NUMBER() to group those duplicate 'RATE' but it also group those rows which are not adjacent to others, so yet I can't merge all of them.
Is it possible for implementing this query without using any if-else or while-loop?
The result must look like:
FirstDate LastDate BaseCUR ConvertedCUR RATE
20070501 20070531 USD........EUR........1.369748
20070601 20070702 USD........EUR........1.354772<<< the dates are merged
20070703 20070731 USD........EUR........1.343621<<< the dates are merged
20070801 20070831 USD........EUR........1.376050
20070901 20071002 USD........EUR........1.369748
Any solutions or directions would be greatly appreciated, thank you in advance.
You can use the following query:
SELECT MIN(FirstDate) AS FirstDate, MAX(LastDate) AS LastDate,
BaseCUR, ConvertedCUR, RATE
FROM (
SELECT *,
ROW_NUMBER() OVER (ORDER BY FirstDate) -
RANK() OVER (PARTITION BY RATE ORDER BY FirstDate) AS rnk
FROM mytable ) t
GROUP BY BaseCUR, ConvertedCUR, RATE, rnk
ORDER BY FirstDate
GROUP BY RATE, rnk identifies islands of successive RATE values. Using MIN, MAX functions we can calculate the starting and ending dates of each of those islands.
Demo here
I would solve this in two steps. Here is pseudo code for the approach I would take:
UPDATE the table, setting FirstDate=MIN(FirstDate) and LastDate=MAX(LastDate) and grouping by all the other columns.
Use ROW_NUMBER to eliminate all duplicate rows.
I'm supposing MERGE will be get the earliest FirsDate and the latest LastDate for the same RATE, BaseCUR and ConvertedCUR.
If that is the case:
SELECT MIN (FirstDate), MAX (LastDate), BaseCUR, ConvertedCUR, RATE FROM YourTable GROUP BY BaseCUR, ConvertedCUR, RATE;
P.S. Please excuse the format, I'm using mobile version on a going jetty.

Resources