I've have an access query that I am trying to run and can't seem to get it right.
I'm already calculating a sum of hours grouped by the name and a description column. I would like the total column basically to give a sum of the hours by the name and the description column
SELECT dbo_t_SAP_AttCodes.Description, Sum(dbo_v_MES_TcActivities.Hours) AS SumOfHours,
Left([supervisor1email],InStr([supervisor1email],".")-1) AS [Supervisor First Name],
Mid([supervisor1email],InStr([supervisor1email],".")+1,
InStr([supervisor1email],"#")-InStr([supervisor1email],".")-1)
AS [Supervisor Last Name], (SELECT sum([hours]) FROM [dbo_v_MES_TcActivities]
WHERE [costctr]="106330" AND [clockin] Between DateAdd("d",-((Weekday(Date())-1)),
Date()) And Date()) AS Total_Hours
FROM dbo_v_MES_TcActivities LEFT JOIN dbo_t_SAP_AttCodes
ON dbo_v_MES_TcActivities.AttCode = dbo_t_SAP_AttCodes.Code
WHERE (((dbo_v_MES_TcActivities.AttCode) Not Like "MEAL")
AND ((dbo_v_MES_TcActivities.CostCtr) Like "106330")
AND ((dbo_v_MES_TcActivities.ClockIn) Between DateAdd("d",-((Weekday(Date())-1)),
Date()) And Date()))
GROUP BY dbo_t_SAP_AttCodes.Description, Left([supervisor1email],
InStr([supervisor1email],".")-1),
Mid([supervisor1email],InStr([supervisor1email],".")+1,
InStr([supervisor1email],"#")-InStr([supervisor1email],".")-1),
dbo_v_MES_TcActivities.Supervisor1Email
ORDER BY Mid([supervisor1email],InStr([supervisor1email],".")+1,
InStr([supervisor1email],"#")-InStr([supervisor1email],".")-1);
EDIT:
Here is what the current output looks like:
before
Here is what I would like to see:
After
Consider turning your subquery to a correlated subquery where you match the nested SELECT statement to corresponding row's name in main query without Description (only Name) grouping. The below comes out long due to Supervisor first and last name calculated expressions.
Please note: below uses table aliases with sub and main (adjust all field references accordingly):
Subquery
SELECT --...same fields/expressions as original w/ 'main' alias...,
(SELECT SUM(sub.[hours]) FROM [dbo_v_MES_TcActivities] sub
WHERE sub.[costctr]="106330"
AND sub.AttCode Not Like "MEAL"
AND sub.[clockin] Between DateAdd("d",-((Weekday(Date())-1)), Date()) And Date()
AND Left(sub.[supervisor1email], InStr(sub.[supervisor1email],".")-1) =
Left(main.[supervisor1email], InStr(main.[supervisor1email],".")-1)
AND Mid(sub.[supervisor1email], InStr(sub.[supervisor1email],".")+1,
InStr(sub.[supervisor1email],"#") - InStr(sub.[supervisor1email],".")-1) =
Mid(main.[supervisor1email], InStr(main.[supervisor1email],".")+1,
InStr(main.[supervisor1email],"#") - InStr(main.[supervisor1email],".")-1)
) AS Total_Hours
FROM dbo_v_MES_TcActivities main
LEFT JOIN dbo_t_SAP_AttCodes sap
ON main.AttCode = sap.Code
--...same WHERE and GROUPBY as original w/ 'main' and 'sap' aliases...
Derived Tables
Alternatively, turn both aggregate queries into derived tables joined into main query. In MS Access you can even save both nested SELECT statements as separate, saved queries and reference them in FROM and JOIN clause. Again, note the table aliases:
SELECT t1.Description, t1.SumOfHours, t1.[Supervisor First Name], t1.[Supervisor Last Name],
t2.TotalHours
FROM (
SELECT --...same fields/expressions as original...
FROM dbo_v_MES_TcActivities main
LEFT JOIN dbo_t_SAP_AttCodes sap
ON main.AttCode = sap.Code
--...same WHERE and GROUPBY as original...
) As t1
INNER JOIN
(
SELECT SUM(sub.[hours]),
Left(sub.[supervisor1email], InStr(sub.[supervisor1email],".")-1)
AS [Supervisor First Name],
Mid(sub.[supervisor1email], InStr(sub.[supervisor1email],".")+1,
InStr(sub.[supervisor1email],"#") - InStr(sub.[supervisor1email],".")-1)
AS [Supervisor Last Name]
FROM [dbo_v_MES_TcActivities] sub
WHERE sub.[costctr]="106330"
AND sub.AttCode Not Like "MEAL"
AND sub.[clockin] Between DateAdd("d",-((Weekday(Date())-1)), Date()) And Date()
GROUP BY
Left(sub.[supervisor1email], InStr(sub.[supervisor1email],".")-1),
Mid(sub.[supervisor1email], InStr(sub.[supervisor1email],".")+1,
InStr(sub.[supervisor1email],"#") - InStr(sub.[supervisor1email],".")-1)
) AS t2
ON t1.[Supervisor First Name] = t2.[Supervisor First Name]
AND t1.[Supervisor Last Name] = t2.[Supervisor Last Name]
Related
I have two tables. One table is the main registered Boat table that holds most of the information. it has many columns one of them is [MFR CODE].
The other table is a reference table that contains all the records associated with only Business Boats and it has only 3 columns : [MFR CODE], [MFR NAME] & [MODEL]
I'm trying to find how many times (count) Business Boats appear in the Registered boat tables.
SELECT
Count(*) As 'TotalNumberBoats'
, [BoatsReg].[dbo].[MASTER].[MFR MDL CODE]
,[BoatsReg].[dbo].[BusinessBoats].[MFR]
,[BoatsReg].[dbo].[BusinessBoats].[MODEL]
FROM [BoatsReg].[dbo].[MASTER],[BoatsReg].[dbo].[BusinessBoats]
Where [BoatsReg].[dbo].[MASTER].[MFR MDL CODE] = [BoatsReg].[dbo].[BusinessBoats].[CODE]
group by [BoatsReg].[dbo].[BusinessBoats].[CODE]
order by TotalNumberBoats asc
How do i get rid of all the square brackets, it's annoying.
why do i get an error ?
Well when you aggregate a result, you have to specify all other fixed columns in the GROUP BY clause
(Answer edited to add total row with a UNION ALL and add a sort field to put the total row as last one)
In your case:
SELECT 1 as sorted,
,Count(*) As TotalNumberBoats
,MASTER.[MFR MDL CODE]
,BusinessBoats.MFR
,BusinessBoats.MODEL
FROM BoatsReg, BusinessBoats
Where MASTER.[MFR MDL CODE] = BusinessBoats.CODE
Group by
,MASTER.[MFR MDL CODE]
,BusinessBoats.MFR
,BusinessBoats.MODEL
UNION ALL
SELECT 2 as sorted,
,Count(*) As TotalNumberBoats
,'','',''
FROM BoatsReg
Order by sorted, TotalNumberBoats
I am trying to put together a query that will basically run another query on each return.
My current query puts together important info for each client, such as how long an average groom takes and the description of the type of haircut they get:
SELECT Query11.petId AS PetID,
Query11.petName AS PetName,
dbo_Customer.cstLName AS LastName,
Query11.lstValue AS Breed,
qryFindsPetAvgApptTime.TotalAppts,
dbo_vwPetGroom.pgrName AS GroomStyle,
dbo_ListValues.lstValue AS Haircut,
ROUND([AvgPTime]) AS AvgPrep,
ROUND([AvgBTime]) AS AvgBath,
ROUND([AvgDTime]) AS AvgDry,
ROUND([AvgGTime]) AS AvgGroom,
[AvgPrep] + [AvgBath] + [AvgDry] + [AvgGroom] AS AvgMinutes,
qryFindsPetAvgApptTime.AvgHours
FROM((Query11
LEFT JOIN qryFindsPetAvgApptTime ON Query11.petId = qryFindsPetAvgApptTime.PetID)
LEFT JOIN dbo_Customer ON Query11.petCustId = dbo_Customer.cstId)
LEFT JOIN (dbo_vwPetGroom
LEFT JOIN dbo_ListValues ON dbo_vwPetGroom.pgrLengthHairBodyLid = dbo_ListValues.lstId)
ON Query11.petId = dbo_vwPetGroom.pgrPetId;
I want to add in the average length between grooming appts to the above query info. Right now that is done in 2 seperate queries.
The first one pulls days between appts:
SELECT tblTimeLog.PetID,
tblTimeLog.PetName,
[ApptDate] - (SELECT MAX(T.ApptDate)
FROM tblTimeLog T
WHERE T.PetID = tblTimeLog.PetID
AND T.ApptDate < tblTimeLog.ApptDate) AS Diff,
tblTimeLog.ApptDate
FROM tblTimeLog
WHERE (((tblTimeLog.PetID) = [Enter PetID]))
ORDER BY tblTimeLog.ApptDate;
And then averaged out with this:
SELECT qryTimeLogDiffs.PetID,
qryTimeLogDiffs.PetName,
AVG(qryTimeLogDiffs.Diff) AS AvgOfDiff
FROM qryTimeLogDiffs
GROUP BY qryTimeLogDiffs.PetID,
qryTimeLogDiffs.PetName;
Is there a way to pass the PetID criteria from each return into the second query so it adds the average span between appts to the info in the first query??
Consider refactoring your second query to avoid the taxing correlated aggregate subquery. One approach involves first running an aggregate query based on a self join to return last appointment date for each PetID.
Even better, turn this query into an action query to populate a temporary table either with make-table query as shown below using INTO or regularly cleaning out a persistent table via delete and insert-select query:
SELECT curr.PetID,
curr.PetName,
curr.ApptDate,
MAX(prev.[AppDate]) AS MaxPrevDate
INTO lastApptTimeLog
FROM tblTimeLog AS curr
INNER JOIN tblTimeLog AS prev
ON curr.PetID = prev.PetID
WHERE prev.ApptDate < curr.AppDate
GROUP BY curr.PetID,
curr.PetName,
curr.ApptDate;
Then, base third aggregate query on this temp table and run the difference calculation. Finally, incorporate this query into first query.
SELECT PetID,
PetName,
AVG(ApptDate - MaxPrevDate) AS AvgOfDiff
FROM lastApptTimeLog
GROUP BY PetID,
PetName;
I have query that contain subquery: to calculate the interval between departure and arrival time, from my table "Timetable"
this Query works very fine, but when trying to execute it from the Crosstab, It prompts me an error that it cannot find table "a" which is alias I used for "Timetable"
SELECT a.VesselID, a.MovementID, a.MovementTime, (SELECT TOP 1
Timetable.MovementTime
FROM Timetable
WHERE (((Timetable.MovementID)="Arrival") AND
((Timetable.VesselID)=a.VesselID]) AND ((Timetable.MovementTime)>a.
[MovementTime]))
ORDER BY Timetable.MovementTime) AS Arrival1,
DateDiff('h',[a].[MovementTime],[Arrival1]) AS [Interval]
FROM Timetable AS a INNER JOIN Timetable ON a.ID = Timetable.ID
WHERE (((a.MovementID)="Departure"));
I think this Question is very similar, and the solution is that I split my query As #DHW said, but I couldn't do that.
and this is my try on splitting:
[Departure_Query]
SELECT Timetable.VesselID, Timetable.MovementTime AS mymov,
Timetable.MovementID
FROM Timetable
WHERE (((Timetable.MovementID)="Departure"));
[Main]
SELECT Timetable.MovementTime, Timetable.MovementID, Timetable.VesselID, Departure_Query.mymov, DateDiff('h',[mymov],[MovementTime]) AS [Interval]
FROM Timetable INNER JOIN Departure_Query ON Timetable.VesselID = Departure_Query.VesselID
WHERE (((Timetable.MovementTime)>[Departure_Query].[mymov]) AND ((Timetable.MovementID)="Arrival") AND ((Timetable.VesselID)=[Departure_Query].[VesselID]))
ORDER BY Timetable.MovementTime;
I think the problem is:
In The working query I could put SELECT TOP 1 but in the split try I dont know where to put it.
update Actually, right now i want to split it anyway, because when i am trying to build a report in top of it. It prompts me that Access cant do grouping on this field.
But anyway this my attempt
TRANSFORM DateDiff('h',[a].[MovementTime],[Arrival1]) AS [Interval]
SELECT a.MovementTime
FROM Timetable AS a INNER JOIN Timetable ON a.ID = Timetable.ID
WHERE (((a.MovementID)="Departure"))
GROUP BY a.MovementID, a.MovementTime, (SELECT TOP 1 Timetable.MovementTime
FROM Timetable
WHERE (((Timetable.MovementID)="Arrival") AND ((Timetable.VesselID)=a.[VesselID]) AND ((Timetable.MovementTime)>a.[MovementTime]))
ORDER BY Timetable.MovementTime)
PIVOT a.VesselID;
The resultsThe Design View
Consider a crosstab with a domain aggregate, DMin() to replace subquery:
TRANSFORM DateDiff('h', main.[MovementTime], main.[Arrival1]) AS [Interval]
SELECT main.MovementID, main.MovementTime
FROM
(SELECT t.VesselID, t.MovementID, t.MovementTime,
DMin("MovementTime", "Timetable", "MovementID = 'Arrival'
AND VesselID = " & t.VesselID & "
AND MovementTime > #" & t.MovementTime & "#") As Arrival1
FROM Timetable AS t
WHERE (((t.MovementID) = 'Departure'))
) As
GROUP BY main.MovementID, main.MovementTime
PIVOT main.VesselID;
Thank you #Parfait and #June7, I am adding this answer so anyone in the future can benefit from this problem.
The Problem
I figured out the problem to be: The query is subtracting all the smaller departure dates for a specific Vessel
i.e. Vessel 1 Departed 6/1, 6/3, 6/6 and Arrived 6/2,6/2,6/8. so for the last day It was subtracting 6/8-6/6, 6/8-6/3, 6/8-6/1. of the course the only first one (the bold one)is the right one.
The Solution
SELECT Min(Timetable.MovementTime) AS MinOfMovementTime, Departure_Query.mymov AS DeptDate, Min(DateDiff('h',[mymov],[MovementTime])) AS WorkingH, Timetable.MovementID, Timetable.VesselID
FROM Timetable LEFT JOIN Departure_Query ON Timetable.VesselID = Departure_Query.VesselID
WHERE (((Timetable.MovementID)="Arrival") AND ((Timetable.VesselID)=[Departure_Query].[VesselID]) AND ((Timetable.MovementTime)>[mymov]))
GROUP BY Departure_Query.mymov, Timetable.MovementID, Timetable.VesselID
ORDER BY Min(Timetable.MovementTime);
The only change here is Min(DateDiff('h',[mymov],[MovementTime])) which only give the smallest subtraction value, which translates to The biggest Departure Date.
I have the following query in SQL Server 2008 R2:
SELECT
DateName(month, DateAdd(month, [sfq].[fore_quart_month], -1)) AS [Month],
[sfq].[fore_quart_so_rev] AS [Sales Orders Revenue],
[sfq].[fore_quart_so_mar] AS [Sales Orders Margin],
[sfq].[fore_quart_mac_rev] AS [MAC Revenue],
[sfq].[fore_quart_mac_mar] AS [MAC Margin],
[sfq].[fore_quart_total_rev] AS [TOTAL Revenue],
[sfq].[fore_quart_total_mar] AS [TOTAL Margin],
(SELECT SUM([FORE].[Revenue])
FROM [SO_Opportunity][SO]
LEFT JOIN [SO_Type] ON [SO].[SO_Type_RecID] = [SO_Type].[SO_Type_RecID]
LEFT JOIN [SO_Opportunity_Audit][soa] ON [so].[Opportunity_RecID] = [soa].[Opportunity_RecId]
LEFT JOIN [SO_Opportunity_Audit_Value][soav] ON [soa].[SO_Opportunity_Audit_RecId] = [soav].[SO_Opportunity_audit_recid]
LEFT JOIN [SO_Forecast_dtl] [FORE] ON [SO].[Opportunity_RecID] = [FORE].[Opportunity_RecID]
WHERE ([SO_Type].[Description] NOT LIKE '%MAC%' AND [SO_Type].[Description] NOT LIKE '%Maint%')
AND YEAR([soa].[last_Updated_utc]) = #p_year AND MONTH([soa].[last_updated_utc]) = [sfq].[fore_quart_month]
AND [soav].[audit_value] LIKE '%Closed - Won%' AND [soav].[audit_token] = 'new_value'
AND [so].[SO_Opp_Status_RecID] = 7) AS [Rev]
FROM
[authmanager2].[dbo].[sales_forecast_quarterly][sfq]
WHERE
[sfq].[fore_quart_year] = #p_year AND [sfq].[fore_quart_loc] = 'w'
ORDER BY
[sfq].[fore_quart_month]
The issue is that when including the NOT LIKE filters and the [sfq].[fore_quart_month] reference in the subquery, it runs incredibly slow (minutes), but if I remove the NOT LIKE filters or if I hard set the value instead of use the [sfq].[fore_quart_month] (which obviously means every calculation will use the wrong month except the one I hard coded), then the query runs in less than a second.
Any suggestions?
The LIKE queries with wild cards on both ends are very slow. Example: %MAC%
If you really need to search on that, consider creating a persisted computed boolean field and searching on that. Something like:
ALTER TABLE SO_Type
ADD IsMac AS CASE WHEN [Description] LIKE '%MAC%' THEN 1 ELSE 0 END PERSISTED
GO
OR
As an alternative, set ISMac whenever data is inserted
Small tip: you can group by month and join subquery to main datasource in from clause. This will let (which is not must) server perform subquery only once. And please note my comment above.
...
FROM [authmanager2].[dbo].[sales_forecast_quarterly][sfq]
INNER JOIN
(
SELECT SUM([FORE].[Revenue]) as [Revenue], MONTH([soa].[last_updated_utc]) as [Month]
FROM [SO_Opportunity][SO]
INNER JOIN [SO_Type] ON [SO].[SO_Type_RecID] = [SO_Type].[SO_Type_RecID]
...
GROUP BY MONTH([soa].[last_updated_utc])
) rev on rev.[Month] = [sfq].[fore_quart_month]
I am a New ASP.NET Developer and I am trying to develop a simple suggestion box system. I have the following part of my database desing:
User Table: Username, Name, DivisionCode... etc
Division Table: SapCode, Division
SuggestionLog Table: ID, Title, Description, submittedDate, Username
(The first attribute is the primary key in each table and the attribute (submittedDate) is of DateTime data type)
Now, I need to develop a table that shows suggestions for the last three months. I already developed a query that shows the Employee Name, Username, Division, Suggestion Title, Suggestion Description. All what I want now is to show the Month. For example, to show the suggestions for the last three months, the Month column should show: Jan-2012, Dec-2011, Nov-2011 So how to do that?
My current SQL query:
SELECT dbo.SafetySuggestionsLog.Title, dbo.SafetySuggestionsLog.Description, dbo.SafetySuggestionsType.Type, dbo.SafetySuggestionsLog.Username,
dbo.employee.Name, dbo.Divisions.DivisionShortcut
FROM dbo.Divisions INNER JOIN
dbo.employee ON dbo.Divisions.SapCode = dbo.employee.DivisionCode INNER JOIN
dbo.SafetySuggestionsLog ON dbo.employee.Username = dbo.SafetySuggestionsLog.Username INNER JOIN
dbo.SafetySuggestionsType ON dbo.SafetySuggestionsLog.TypeID = dbo.SafetySuggestionsType.ID
The desired output is to display:
Employee Name, Username, Division, SuggestionTitle, SuggstionDescription, SuggestionType Month(submissionDate)
I reformatted you query so it would fit on the page without scrolling.
Hopefully this provides what you need. It uses DATENAME to get the month and year parts from the current date and DATEPART to do the "three months ago" calculation.
Note that DATEPART doesn't behave as you might expect - it counts the number of period-end boundaries (in this case months) - hence the condition is
...WHERE DATEDIFF(month,SafetySuggestionsLog.submittedDate,getdate()) < 3
because the last three months have two month-end boundaries between them.
I also added an ORDER BY clause.
SELECT dbo.SafetySuggestionsLog.Title,
dbo.SafetySuggestionsLog.Description,
dbo.SafetySuggestionsType.Type,
dbo.SafetySuggestionsLog.Username,
dbo.employee.Name,
dbo.Divisions.DivisionShortcut,
left(datename(month,SafetySuggestionsLog.submittedDate),3)
+ '-'
+ datename(year,SafetySuggestionsLog.submittedDate) AS SubmittedMonth
FROM dbo.Divisions
INNER JOIN dbo.employee
ON dbo.Divisions.SapCode = dbo.employee.DivisionCode
INNER JOIN dbo.SafetySuggestionsLog
ON dbo.employee.Username = dbo.SafetySuggestionsLog.Username
INNER JOIN dbo.SafetySuggestionsType
ON dbo.SafetySuggestionsLog.TypeID = dbo.SafetySuggestionsType.ID
WHERE DATEDIFF(month,SafetySuggestionsLog.submittedDate,getdate()) < 3
ORDER BY SafetySuggestionsLog.submittedDate DESC
It might also be worth noting that you don't have to fully qualify the name of all the columns in the query - it's valid SQL to alias the input tables like so:
...INNER JOIN dbo.SafetySuggestionsLog AS log
You can then refer to column names by alias in the query - e.g.
log.Username
instead of
dbo.SafetySuggestionsLog.Username
which makes it a bit easier to read.