aggregate function warning by group clause - sql

So ive been running to this problem constantly and maybe someone can give me a good explanation in how or why it wouldn't work. I'm trying to GROUP BY just one column CSHFutureTAs.Time and ive tried integrating the simple line
GROUP BY CSHFutureTAs.Time
however this gives me an error "You tried to execute a query that does not include the specified expression 'TA' as part of an aggregate function", can anyone help me ??
Complete SQL (without the GROUP CLAUSE):
SELECT CSHFutureTAs.TA
, CSHFutureTAs.TIME AS CSHGeneralTAs_TIME
, CSHFutureTAs.[CUT OFF TIME]
, CSHFutureTAs.SUNDAY AS CSHGeneralTAs_SUNDAY
, CSHFutureTAs.MONDAY AS CSHGeneralTAs_MONDAY
, CSHFutureTAs.TUESDAY AS CSHGeneralTAs_TUESDAY
, CSHFutureTAs.WEDNESDAY AS CSHGeneralTAs_WEDNESDAY
, CSHFutureTAs.THURSDAY AS CSHGeneralTAs_THURSDAY
, CSHFutureTAs.FRIDAY AS CSHGeneralTAs_FRIDAY
, CSHFutureTAs.SATURDAY AS CSHGeneralTAs_SATURDAY
, FUT_Totals.TIME AS GeneralTotals_Time
, FUT_Totals.SUNDAY AS GeneralTotals_SUNDAY
, FUT_Totals.MONDAY AS GeneralTotals_MONDAY
, FUT_Totals.TUESDAY AS GeneralTotals_TUESDAY
, FUT_Totals.WEDNESDAY AS GeneralTotals_WEDNESDAY
, FUT_Totals.THURSDAY AS GeneralTotals_THURSDAY
, FUT_Totals.FRIDAY AS GeneralTotals_FRIDAY
, FUT_Totals.SATURDAY AS GeneralTotals_SATURDAY
, CSHFutureTAs.[EXCEPTION DAYS]
, CSHFutureTAs.[EXCEPTION VALUE]
, IIf([FUT_Totals] ! [Time] = "09:00 - 21:00"
OR [FUT_Totals] ! [Time] = "10:00 - 22:00", 9, 1) AS SortKey
FROM
(
CSHFutureTAs
INNER JOIN FUT_Totals ON (CSHFutureTAs.[HG ID] = FUT_Totals.HG_ID)
AND (CSHFutureTAs.TIME = FUT_Totals.TIME)
)
INNER JOIN Current_INFO ON (CSHFutureTAs.[HG ID] = Current_INFO.[HG ID])
AND (CSHFutureTAs.[HEADER ID] = Current_INFO.[HEADER ID])
AND (FUT_Totals.HG_ID = Current_INFO.[HG ID])
ORDER BY IIf([FUT_Totals] ! [Time] = "09:00 - 21:00"
OR [FUT_Totals] ! [Time] = "10:00 - 22:00", 9, 1);

where exactly is your GROUP BY CSHFutureTAs.Time clause?
you need to group by one column, and any other column that is not part of the group must have an aggregation function on it like SUM or AVG for example.
Also I dont think you need that parentesys on your FROM. Why did you add that?

Related

How to use a SUM, LEFT JOIN, group by and order by in one SQL statement

I am trying to construct a query I can use within my ASP.NET code that pulls from a data base and then exports it into an excel file. My goal is to have SQL do most of the work before I iterate onto my worksheet. This is my code before using sum and group by
SELECT EOD_Rental_Fees.*, POSH5_Prod_CoreBankingDetails.description as TotalFeeAmount)
FROM EOD_Rental_Fees
LEFT JOIN POSH5_Prod_CoreBankingDetails ON EOD_Rental_Fees.CoreBankingID = POSH5_Prod_CoreBankingDetails.ID
WHERE DateProcessed >= '2018-07-01 00:00:00.000'
AND DateProcessed <= '2018-08-30 00:00:00:000'
ORDER BY description, DateProcessed;
This is the result of it:
When I add SUM or GROUP BY like so
Select EOD_Rental_Fees.*, POSH5_Prod_CoreBankingDetails.description, (Select SUM (EOD_Rental_Fees.TotalFee) as TotalFeeAmount) from
EOD_Rental_Fees
LEFT JOIN POSH5_Prod_CoreBankingDetails ON EOD_Rental_Fees.CoreBankingID = POSH5_Prod_CoreBankingDetails.ID
WHERE DateProcessed >= '2018-07-01 00:00:00.000'
AND DateProcessed <= '2018-08-30 00:00:00:000'
Group By Currency
Order By description, DateProcessed;
I get the following error: I am trying to have a column that shows TotalFeeAmount that is grouped by Currency.
From what I can see my query looks fine. What am I doing wrong to cause this?
What I am trying to achieve is something like this:
You keep adding to the question which makes it difficult to answer. In the latest image you are displaying a report - not a query result, so I am going to ignore the sub-totals and that i something for your presentation layer to deal with.
"From what I can see my query looks fine" Sorry, it isn't fine because it produces SQL errors. That error actually tells you that if you want to use group by you must specify which columns to be grouped by. Your query does not do that.
To avoid that error every "non-aggregating" column needs to be spelled out in the group by clause like so (note you cannot use * for this)
SELECT
rf.id
, rf.year
, rf.month
, rf.DateProcessed
, rf.CoreBankingID
, rf.MerchantRecordID
, rf.DeployedDate
, rf.TerminalRecordID
, rf.DeployedDate
, rf.RecoveredDate
, rf.MonthlyFee
, rf.IsProRated
, rf.DaysActive
, rf.TotalFee
, rf.IsPinPad
, rf.Currency
, det.description
, sum(rf.TotalFee) as TotalFeeAmount
FROM EOD_Rental_Fees AS rf
LEFT JOIN POSH5_Prod_CoreBankingDetails as det ON rf.CoreBankingID = det.ID
WHERE rf.DateProcessed >= '2018-07-01 00:00:00.000'
AND rf.DateProcessed < '2018-09-01 00:00:00:000'
GROUP BY
rf.id
, rf.year
, rf.month
, rf.DateProcessed
, rf.CoreBankingID
, rf.MerchantRecordID
, rf.DeployedDate
, rf.TerminalRecordID
, rf.DeployedDate
, rf.RecoveredDate
, rf.MonthlyFee
, rf.IsProRated
, rf.DaysActive
, rf.TotalFee
, rf.IsPinPad
, rf.Currency
, det.description
ORDER BY
det.description
, rf.DateProcessed
However I suspect this isn't going to produce the wanted outcome because you are after both details and summary at the same time which GROUP BY isn't designed to achieve.
I think you will find using SUM() OVER() will be closer to you need, but exactly how you need the PARTITION BY subclause to work isn't clear to me. notwithstanding this may work for you:
SELECT
rf.id
, rf.year
, rf.month
, rf.DateProcessed
, rf.CoreBankingID
, rf.MerchantRecordID
, rf.DeployedDate
, rf.TerminalRecordID
, rf.DeployedDate
, rf.RecoveredDate
, rf.MonthlyFee
, rf.IsProRated
, rf.DaysActive
, rf.TotalFee
, rf.IsPinPad
, rf.Currency
, det.description
, sum(rf.TotalFee) over(partition by rf.CoreBankingID, Currency) as TotalFeeAmount
FROM EOD_Rental_Fees AS rf
LEFT JOIN POSH5_Prod_CoreBankingDetails as det ON rf.CoreBankingID = det.ID
WHERE rf.DateProcessed >= '2018-07-01 00:00:00.000'
AND rf.DateProcessed < '2018-09-01 00:00:00:000'
ORDER BY
det.description
, rf.DateProcessed
Notes:
Use table aliases to simplify your queries
when joining tables include the table aliases in all column references
I subtly changed the way the date range works, always use a combination of >= with < and the upper boundary is "the next day". With this approach you cover yourself for any data rows that have both date and time.
here is how you can do it by using GROUP BY ROLLUP:
Select
DESCRIPTION
, currency
, DateProcessed
SUM (EOD_Rental_Fees.TotalFee)
from
EOD_Rental_Fees
LEFT JOIN POSH5_Prod_CoreBankingDetails
ON EOD_Rental_Fees.CoreBankingID = POSH5_Prod_CoreBankingDetails.ID
WHERE
DateProcessed >= '2018-07-01 00:00:00.000'
AND DateProcessed <= '2018-08-30 00:00:00:000'
GROUP BY ROLLUP (DESCRIPTION, currency, DateProcessed)
Order By
description,DateProcessed;

How to return current and previous row in SQL?

How do I return the current row and the previous row in a SQL query that is organized by date on a join? I have to join the "Crew" table with its "Detail" table. When I execute the query using a subselect, I get the same data for each crew. I am not sure how to pass the current crew ID down to the subselect so that only the previous days work for the current crew is returned.
SELECT Spread_Crew.Description
, Sum(Abs(Daily_Progress.Station_Number_
Begin_Daily_Progress.Station_Number_End)) AS [Feet Total]
, Spread_Crew.Hourly_Employee_Count AS [Hourly]
, Spread_Crew.Salary_Employee_Count AS [Salary]
, (Spread_Crew.Hourly_Employee_Count +
Spread_Crew.Salary_Employee_Count)*10 AS [Weekly Hours]
, (Date() - Spread_Crew.Actual_Start_Date) AS [Crew Days to Date]
, Round(([Feet Total]/ [Crew Days to Date]),0) AS [FT/Day]
, (SELECT Sum(Abs(Daily_Progress.Station_Number_Begin
Daily_Progress.Station_Number_End))
FROM Spread_Crew INNER JOIN Daily_Progress ON Spread_Crew.ID =
Daily_Progress.Spread_Crew_Id
WHERE (((Daily_Progress.PROGRESS_DATE)=[Report Date]))
) AS [Previous Footage]
FROM Spread_Crew LEFT JOIN Daily_Progress ON Spread_Crew.ID =
Daily_Progress.Spread_Crew_Id
GROUP BY Spread_Crew.Description
, Spread_Crew.Hourly_Employee_Count
, Spread_Crew.Salary_Employee_Count
, Spread_Crew.Sort_Order
, Spread_Crew.Print_On_Daily_Report
, Spread_Crew.Actual_Start_Date
HAVING (((Spread_Crew.Print_On_Daily_Report)=True))
ORDER BY Spread_Crew.Sort_Order;
Your subquery probably wants to be a correlated subquery:
(SELECT Sum(Abs(dp.Station_Number_Begin - dp.Station_Number_End))
FROM Daily_Progress as dp
WHERE Spread_Crew.ID = dp.Spread_Crew_Id AND
dp.PROGRESS_DATE = [Report Date]
) AS [Previous Footage]
The expression Spread_Crew.ID refers to the column in the outer SELECT.

How to group some records by name and pivot some values

I am working on a SQL Query to group the results of a View by Id to have only one Row per Id
with a maximum of three pivoted results and keeping some columns static : TestCaseId, TestName, Test Case Num, Owner
Actually this is the Query i Created to get the Desired output but is now working as expected because the MAX is always retriving the max value so i am getting only one row but the pivoted values are repeated to the right.
SELECT DISTINCT TBL1.[TestName], TBL1.[Test Case Num], TBL1.[Owner], MAX(TBL1.[Browser]) as 'Column1', MAX(TBL1.[Run Date]) as 'Column2', MAX(TBL1.[Status]) as 'Column3', MAX(TBL1.[Duration]) as 'Column4', MAX(TBL1.[ErrorMsg]) as 'Column5', MAX(TBL2.[Browser]) as 'Column6', MAX(TBL2.[Run Date]) as 'Column7', MAX(TBL2.[Status]) as 'Column8', MAX(TBL2.[Duration]) as 'Column9', MAX(TBL2.[ErrorMsg]) as 'Column10', MAX(TBL3.[Browser]) as 'Column11' , MAX(TBL3.[Run Date]) as 'Column12', MAX(TBL3.[Status]) as 'Column13', MAX(TBL3.[Duration]) as 'Column14', MAX(TBL3.[ErrorMsg]) as 'Column15'
FROM (SELECT DISTINCT T1.[TestCaseId], T1.[TestName], T1.[Test Case Num], T1.[Owner], T1.[Browser], T1.[Run Date], T1.[Status], T1.[Duration], T1.[ErrorMsg]
FROM [TestRunner].[dbo].RunsRawResults T1) TBL1
cross apply (SELECT DISTINCT T2.[TestCaseId], T2.[Browser], T2.[Run Date], T2.[Status], T2.[Duration], T2.[ErrorMsg]
FROM [TestRunner].[dbo].RunsRawResults T2
WHERE T2.[TestCaseId] = TBL1.[TestCaseId] AND T2.[Run Date] TBL1.[Run Date]) TBL2
cross apply (SELECT DISTINCT T3.[TestCaseId], T3.[Browser], T3.[Run Date], T3.[Status], T3.[Duration], T3.[ErrorMsg]
FROM [TestRunner].[dbo].RunsRawResults T3
WHERE T3.[TestCaseId] = TBL2.[TestCaseId] AND T3.[Run Date] TBL2.[Run Date] AND T3.[Run Date] TBL1.[Run Date]) TBL3
GROUP BY TBL1.[TestCaseId], TBL1.[TestName], TBL1.[Test Case Num], TBL1.[Owner]
Input -
Raw Data (Comes from the RunRawResults View)
Desired and Pivoted Output
Using a common table expression (cte) and row_number() we can simplify the identification and order of multiple run dates. This also lets us skip using distinct and group by.
Switching to outer apply lets us include results where there are less than 3 runs per TestCaseId.
;with cte as (
select *
, rn = row_number() over (
partition by TestCaseId
order by [Run Date]
)
from TestRunner.dbo.RunsRawResults
)
select
tbl1.TestName
, tbl1.[Test Case Num]
, tbl1.Owner
, tbl1.Browser
, [Run Date]_tbl1 = tbl1.[Run Date]
, Status_tbl1 = tbl1.Status
, Duration_tbl1 = tbl1.Duration
, ErrorMsg_tbl1 = tbl1.ErrorMsg
, Browser_tbl2 = tbl2.Browser
, [Run Date]_tbl2 = tbl2.[Run Date]
, Status_tbl2 = tbl2.Status
, Duration_tbl2 = tbl2.Duration
, ErrorMsg_tbl2 = tbl2.ErrorMsg
, Browser_tbl3 = tbl3.Browser
, [Run Date]_tbl3 = tbl3.[Run Date]
, Status_tbl3 = tbl3.Status
, Duration_tbl3 = tbl3.Duration
, ErrorMsg_tbl3 = tbl3.ErrorMsg
from cte as tbl1
outer apply (
select
i.[Run Date]
, i.Status
, i.Duration
, i.ErrorMsg
from cte as i
where i.TestCaseId = tbl1.TestCaseId
and i.rn = 2
) as tbl2
outer apply (
select
i.[Run Date]
, i.Status
, i.Duration
, i.ErrorMsg
from cte as i
where i.TestCaseId = tbl1.TestCaseId
and i.rn = 3
) as tbl3
where tbl1.rn = 1

Crosstab data in SQL results

I got this kind of data on my db.
I need to show a result like this:
Using crystal reports this is doable. Hope someone can help me write a query for this.
This is not something that you would normally do using SQL, much better to implement in the application. But if you wanted to do it then you could do something like this:
SELECT Item,
[01/01/2016 - Unique Emp ID] = Count(Distinct iif([Date] = Convert(date, '01-01-2016', [Emp ID], NULL)),
[01/01/2016 - Sum Qty] = Sum(iif([Date] = Convert(date, '01-01'2016', [Qty Bought], NULL)),
[02/01/2016 - Unique Emp ID] = Count(Distinct iif([Date] = Convert(date, '02-01-2016', [Emp ID], NULL)),
...
FROM MyTable;
The downside here is that the column headings are fixed. That's why you should do this in the application.

Access to SQL Query Conversion containing FIRST()

I am converting an MS Access query to a SQL Server stored procedure. I get to this point:
SELECT
AuthNum, AuthStatus, DateCreated,
MIN(DateInitiated) AS DateInitiated,
EventClassification,
FIRST(PlaceOfService) AS PlaceOfService,
Lob, MemId,
MAX(NoticeDate) AS NoticeDate,
MAX(Tat) AS Tat,
FIRST(StaffId) AS StaffId
FROM
PA_TAT_Detailed
GROUP BY
AuthNum, AuthStatus, DateCreated, EventClassification, Lob, MemId
HAVING
((FIRST(PlaceOfService) <> 'Inpatient Hospital')
AND (FIRST(PlaceOfService) <> 'Office - Dental')
AND (FIRST(PlaceOfService) <> 'Dialysis Center'))
AND
((MAX(Tat) Is Null) OR ((MAX(Tat) >= 0) AND (MAX(Tat) <= 28)))
ORDER BY
AuthNum;
But I don't know how to converted the FIRST operator. Any thoughts? Do I need to add an ORDER BY associated with the GROUP BY so I can TAKE 1 perhaps?
Does MIN give the same result in this case?
BTW PlaceOfService, StaffId are strings.
Something like this should be pretty close. Double check that this returns the right info.
SELECT top 1 AuthNum
, AuthStatus
, DateCreated
, MIN(DateInitiated) AS DateInitiated
, EventClassification
, PlaceOfService
, Lob
, MemId
, MAX(NoticeDate) AS NoticeDate
, MAX(Tat) AS Tat
, StaffId
FROM PA_TAT_Detailed
where PlaceOfService not in ('Inpatient Hospital', 'Office - Dental', 'Dialysis Center')
GROUP BY AuthNum
, AuthStatus
, DateCreated
, EventClassification
, PlaceOfService
, Lob
, MemId
, StaffId
HAVING MAX(Tat) Is Null
OR (MAX(Tat) >= 0 AND MAX(Tat) <= 28)
ORDER BY AuthNum;