SQL filter result to current month and previous two months - sql

Here is my sql code:
SELECT Month = datename(month,dateadd(mm,datediff(mm,0,StartTime),0)),
Cast ((ROUND(((CONVERT(DECIMAL(10,2),SUM(Duration)/60)/60)),2)*55) AS numeric(36,2))
FROM VExecutionGlobalHistory Where Tester <> 'dit2988' AND TestTypeID = 1
group by dateadd(mm,datediff(mm,0,StartTime),0), year(dateadd(mm,datediff(mm,0,StartTime),0))
order by dateadd(mm,datediff(mm,0,StartTime),0), year(dateadd(mm,datediff(mm,0,StartTime),0))
This query returns:
April|123
May|3456
June|856
July|345
I want it to return the following:
May|3456
June|856
July|345
Does anyone have any ideas? Im using Microsoft SQL Server Management Studio 2010

The following will return the first day of the month, 2 months back from today:
SELECT CAST(DATEADD(month, DATEDIFF(month, 0, GETDATE())-2, 0)AS DATE)
So you can add to your WHERE criteria:
SELECT Month = datename(month,dateadd(mm,datediff(mm,0,StartTime),0)),
Cast ((ROUND(((CONVERT(DECIMAL(10,2),SUM(Duration)/60)/60)),2)*55) AS numeric(36,2))
FROM VExecutionGlobalHistory
Where Tester <> 'dit2988' AND TestTypeID = 1
AND StartTime >= CAST(DATEADD(month, DATEDIFF(month, 0, GETDATE())-2, 0) AS DATE)
group by dateadd(mm,datediff(mm,0,StartTime),0), year(dateadd(mm,datediff(mm,0,StartTime),0))
order by dateadd(mm,datediff(mm,0,StartTime),0), year(dateadd(mm,datediff(mm,0,StartTime),0))

SELECT TOP 12 b.Month, b.Amount
FROM
(
SELECT TOP 12 a.Year, a.SortMonth, a.Month, a.Amount
FROM
(
SELECT
Year = datename(Year,StartTime),
SortMonth = month(StartTime),
Month = datename(month,dateadd(mm,datediff(mm,0,StartTime),0)),
Amount = Cast ((ROUND(((CONVERT(DECIMAL(10,2),SUM(Duration)/60)/60)),2)*55) AS numeric(36,2))
FROM VExecutionGlobalHistory
Where Tester <> 'dit2988'
AND TestTypeID = 1
group by
datename(Year,StartTime),
month(StartTime),
dateadd(mm,datediff(mm,0,StartTime),0),
year(dateadd(mm,datediff(mm,0,StartTime),0))
) a
ORDER BY a.Year, a.SortMonth DESC
) b
ORDER BY b.Year, b.SortMonth

Related

year to date running total for fiscal year

SELECT DISTINCT
ACCOUNTDATE
,PROPERTYNAME
,rt.management
from aaa t
cross apply
(select SUM(MANAGEMENT) as management
from aaa
where
PROPERTYNAME = t.PROPERTYNAME and
ACCOUNTDATE BETWEEN dateadd(MONTH, datediff(MONTH, 0,t.ACCOUNTDATE),0) -- start of month
AND t.ACCOUNTDATE
) as rt
WHERE AccountDate BETWEEN #STARTOFMONTH_MAN AND #ENDOFMONTH_MAN
ORDER BY AccountDate
This is the query to find month to date.
How to find year to date for fiscal year from the same query?
eg: running total from 01/04/2015-31/03/2016
Not sure from wich date you need the FY start. Suppose from #STARTOFMONTH_MAN. Then you can get FY start as
declare #fymonth int = 4; -- first month of FY.
declare #STARTOFMONTH_MAN date = '20160320';
select fyStart = dateadd(MONTH,
#fymonth - CASE WHEN month(#STARTOFMONTH_MAN) >= #fymonth THEN 1 ELSE 13 END,
dateadd(YEAR, datediff(YEAR, 0, #STARTOFMONTH_MAN),0));
You may simplify those dates calculations by creating calendar table.
EDIT
Idea is to restrict data in WHERE with the larger interval and conditionally SUM data for the subinterval.
declare #fymonth int = 4; -- first month of FY.
SELECT DISTINCT
ACCOUNTDATE
,PROPERTYNAME
,rt.FYManagement, rt.MonthManagement
FROM aaa t
CROSS APPLY
(SELECT
SUM(t2.MANAGEMENT) AS FYManagement
,SUM(CASE WHEN t2.ACCOUNTDATE BETWEEN
-- start of month for t.ACCOUNTDATE
dateadd(MONTH, datediff(MONTH, 0, t3.ACCOUNTDATE), 0)
AND t3.ACCOUNTDATE
THEN t2.MANAGEMENT END) AS MonthManagement
from aaa t2
JOIN aaa t3 ON t3.primarykey = t.primarykey -- change as needed to get 1 to 1 JOIN
where
t2.PROPERTYNAME = t.PROPERTYNAME and
t2.ACCOUNTDATE BETWEEN
-- FY start for t.ACCOUNTDATE
dateadd(MONTH,
#fymonth - CASE WHEN month(t.ACCOUNTDATE) >= #fymonth THEN 1 ELSE 13 END,
dateadd(YEAR, datediff(YEAR, 0, t.ACCOUNTDATE), 0));
AND t.ACCOUNTDATE
) as rt
WHERE AccountDate BETWEEN #STARTOFMONTH_MAN AND #ENDOFMONTH_MAN
ORDER BY AccountDate
declare #fymonth int = 4; -- first month of FY.
SELECT DISTINCT
ACCOUNTDATE
,PROPERTYNAME
,rt.FYManagement, rt.MonthManagement
FROM aaa t
CROSS APPLY
(SELECT
SUM(t2.MANAGEMENT) AS FYManagement
,SUM(CASE WHEN t2.ACCOUNTDATE BETWEEN
-- start of month for t.ACCOUNTDATE
dateadd(MONTH, datediff(MONTH, 0, t3.ACCOUNTDATE), 0)
AND t3.ACCOUNTDATE
THEN t2.MANAGEMENT END) AS MonthManagement
from aaa t2
JOIN aaa t3 ON t3.primarykey = t.primarykey -- change as needed to get 1 to 1 JOIN
where
t2.PROPERTYNAME = t.PROPERTYNAME and
t2.ACCOUNTDATE BETWEEN
-- FY start for t.ACCOUNTDATE
dateadd(MONTH,
#fymonth - CASE WHEN month(t.ACCOUNTDATE) >= #fymonth THEN 1 ELSE 13 END,
dateadd(YEAR, datediff(YEAR, 0, t.ACCOUNTDATE), 0));
AND t.ACCOUNTDATE
) as rt
WHERE AccountDate BETWEEN #STARTOFMONTH_MAN AND #ENDOFMONTH_MAN
ORDER BY AccountDate

Select first and last record each day

I have a table with an engineerID, DateTimeCreated as DateTime, JobID and AuditTypeID
I need a query shows first (engineerID, JobID with AuditTypeID 1) and last (engineerID, JobID with AuditTypeID 2) on each row of the query.
SELECT TOP (100) PERCENT
dbo.AuditTrail.EngineerId,
dbo.AuditTrail.AuditTypeId,
dbo.Engineers.Name,
dbo.Engineers.EngineerTypeCode,
dbo.AuditTrail.JobId,
CAST(dbo.AuditTrail.DateTimeCreated AS Date) AS _Date
FROM
dbo.AuditTrail
INNER JOIN
dbo.Engineers
ON dbo.AuditTrail.EngineerId = dbo.Engineers.EngineerId
WHERE
(dbo.AuditTrail.AuditTypeId = 1) AND
(dbo.Engineers.EngineerTypeCode = 'p') AND
(dbo.Engineers.EngineerTypeCode = 'p') AND
(DATEPART(mm, dbo.AuditTrail.DateTimeCreated) = 6) AND
(DATEPART(YYYY, dbo.AuditTrail.DateTimeCreated) = 2014)
group by
AuditTrail.engineerID,
JobID,
AuditTypeId,
Engineers.name,
Engineers.EngineerTypeCode,
CAST(dbo.AuditTrail.DateTimeCreated AS Date)
ORDER BY
dbo.AuditTrail.EngineerID DESC
for the first part of my query. Unfortunatly I cannot see to select the first record for each day
Any help will be greatly appreciated
First just get the data you need, including the create date. Then grouping that data by date, select the min of each day. Finally, join the two sets, selecting only the minimum of each day -- that is, the first occurrence of each day.
with
AllMonth( EngineerId, AuditTypeId, Name, EngineerTypeCode, JobId, DateTimeCreated )as(
SELECT TOP (100) PERCENT
a.EngineerId,
a.AuditTypeId,
e.Name,
e.EngineerTypeCode,
a.JobId,
a.DateTimeCreated
FROM dbo.AuditTrail a
JOIN dbo.Engineers e
ON e.EngineerId = a.EngineerId
AND e.EngineerTypeCode = a.EngineerTypeCode
WHERE
a.AuditTypeId = 1
AND a.EngineerTypeCode = 'p'
AND a.DateTimeCreated >= DateAdd( mm, DateDiff( mm, 0, GetDate()), 0)
AND a.DateTimeCreated < DateAdd( mm, DateDiff( mm, 0, GetDate()) + 1, 0)
),
FirstByDay( MinDate )as(
select Min( DateTimeCreated )
from AllMonth
group by cast( DateTimeCreated AS Date )
)
select *
from AllMonth a
join FirstByDay f
on f.MinDate = a.DateTimeCreated
ORDER BY a.EngineerID DESC;
To get the last item of each day, just add a max to FirstByDay and add to the join. Work it into one long row if you really want to.
Btw, didn't I hear a few years back that the later versions of MSSQL ignored top (100) percent? I don't work with it much these days, and my memory is...well, just...somewhere around here...

Group a query by every month

I have the following query :
select
(select Sum(Stores) from XYZ where Year = '2013' and Month = '8' )
-
(select Sum(SalesStores) from ABC where Year = '2013' and Month = '8') as difference
Here in the above query Year and Month are also columns of a table.
I would like to know if there is a way to run the same query so that , it is run against every month of the year ?
If there are months without data/rows within XYZ or ABC tables then I would use FULL OUTER JOIN:
SELECT ISNULL(x.[Month], y.[Month]) AS [Month],
ISNULL(x.Sum_Stores, 0) - ISNULL(y.Sum_SalesStores, 0) AS Difference
FROM
(
SELECT [Month], Sum(Stores) AS Sum_Stores
FROM XYZ
WHERE [Year] = '2013'
GROUP BY [Month]
) AS x
FULL OUTER JOIN
(
SELECT [Month], Sum(SalesStores) AS Sum_SalesStores
FROM ABC
WHERE [Year] = '2013'
GROUP BY [Month]
) AS y ON x.[Month] = y.[Month]
;WITH Months(Month) AS
(
SELECT 1
UNION ALL
SELECT Month + 1
FROM Months
where Month < 12
)
SELECT '2013' [Year], m.Month, COALESCE(SUM(Stores), 0) - COALESCE(SUM(SalesStores), 0) [Difference]
FROM months m
LEFT JOIN XYZ x ON m.Month = x.Month
LEFT JOIN ABC a ON a.Month = m.Month
GROUP BY m.Month
You could use GROUP BY in your inner trades, and then run a join, like this:
SELECT left.Month, (left.sum - COALESCE(right.sum, 0)) as difference
FROM (
SELECT Month, SUM(Stores) as sum
FROM XYZ WHERE Year = '2013'
GROUP BY Month
) left
LEFT OUTER JOIN (
SELECT Month, SUM(Stores) as sum
FROM ABC WHERE Year = '2013'
GROUP BY Month
) right ON left.Month = right.Months
Note the use of COALESCE. It lets you preserve the value of the first SUM in case when there are no records for the month in the ABC table.
In the following example uses the UNION ALL operator with CTE
;WITH cte AS
(SELECT SUM(Stores) AS Stores, [Month]
FROM dbo.XYZ
WHERE [Year] = '2013'
GROUP BY [Month]
UNION ALL
SELECT -1.00 * SUM(SalesStores), [Month]
FROM dbo.ABC
WHERE [Year] = '2013'
GROUP BY [Month]
)
SELECT [Month], SUM(Stores) AS Difference
FROM cte
GROUP BY [Month]
Demo on SQLFiddle
;WITH Months(Month) AS
(
SELECT 1
UNION ALL
SELECT Month + 1
FROM Months
where Month < 12
)
SELECT Months. Month ,
(select isnull(Sum(Stores),0) from XYZ where Year = '2013' and Month = Months.Month) - (select isnull(Sum(SalesStores),0) from ABC where Year = '2013' and Month =Months.Month) as difference
FROM Months

Multiple Selects into one select

I'm trying to put some data together for a High Charts Bar chart using ASP.NET. Basically, i have three users who i need to track when they have logged into the system. the variants to be used are:
1) Today
2) This Week
3) Last Week
4) Last Month
So, i've created individual tsql scripts for today and and last week, but i'm now a little stuck on how to combine the two statemets, which will eventually be four.
SELECT Count(*) as CountToday from hitsTable WHERE Convert(date,hitDate) =
Convert(date,GETDATE()) Group by UserId
SELECT count(*) as CountLatWeek from hitTable
where hitDate between (DATEADD(week, DATEDIFF (week,0,GETDATE()),-1))
AND getDate() Group by UserId
Searhing on google, leads me to nested select statements, which all seem to form dependacies with the two statements. However, what i need to do is produce a table of results like this:
EDIT
I've set up a SQL Fiddle, so we can test out the examples
http://www.sqlfiddle.com/#!6/a21ec
the fiddle has tsql for today and tsql for last week (which may need some tweaking)
Select Distinct
UserId
, ( Select Count(*) as CountToday from hitsTable h2
Where h2.UserId = h1.UserId
And Convert(date,hitDate) = Convert(date,GETDATE())
) As CountToday
, ( Select count(*) as CountLatWeek from hitsTable h2
Where h2.UserId = h1.UserId
And hitDate Between DATEADD(dd, -(DATEPART(dw, GetDate())-1)-7, GetDate())
And DATEADD(dd, 7-(DATEPART(dw, GetDate()))-7, GetDate())
) As CountLastWeek
FROM hitsTable h1
Here’s another alternative based on #Avinash comment on the question.
Select
UserId
, CountTodayTable.CountToday
, CountLatWeekTable.CountLatWeek
, ...
FROM hitsTable h1
Inner Join
( Select Count(*) as CountToday from hitsTable h2
Where h2.UserId = h1.UserId
And Convert(date,hitDate) = Convert(date,GETDATE())
) CountTodayTable
On CountTodayTable.UserId = h1.UserId
Inner Join
( Select count(*) as CountLatWeek from hitTable h2
Where h2.UserId = h1.UserId
And hitDate between (DATEADD(week, DATEDIFF (week,0,GETDATE()),-1)) And getDate()
) CountLatWeekTable
On CountLatWeekTable.UserId = h1.UserId
...
Try this query
select
id,
sum(case when Convert(date,hitDate) = Convert(date,GETDATE()) then 1 else 0 end) as as CountToday,
sum(hitDate between (DATEADD(week, DATEDIFF (week,0,GETDATE()),-1)) AND getDate() then 1 else 0 end) as CountLatWeek,
...... -- Add more condition
from
hitsTable
group by
UserId
Edit
select
userid,
sum(case when Convert(date,hitDate) =
Convert(date,GETDATE()) then 1 else 0 end) as cnt
from
hitstable
group by userid
FIDDLE
| USERID | CNT |
|--------|-----|
| User1 | 3 |
| User2 | 0 |

How to output only one max value from this query in SQL?

Yesterday Thomas helped me a lot by providing exactly the query I wanted. And now I need a variant of it, and hopes someone can help me out.
I want it to output only one row, namely a max value - but it has to build on the algorithm in the following query:
WITH Calendar AS (SELECT CAST(#StartDate AS datetime) AS Date
UNION ALL
SELECT DATEADD(d, 1, Date) AS Expr1
FROM Calendar AS Calendar_1
WHERE (DATEADD(d, 1, Date) < #EndDate))
SELECT C.Date, C2.Country, COALESCE (SUM(R.[Amount of people per day needed]), 0) AS [Allocated testers]
FROM Calendar AS C CROSS JOIN
Country AS C2 LEFT OUTER JOIN
Requests AS R ON C.Date BETWEEN R.[Start date] AND R.[End date] AND R.CountryID = C2.CountryID
WHERE (C2.Country = #Country)
GROUP BY C.Date, C2.Country OPTION (MAXRECURSION 0)
The output from above will be like:
Date Country Allocated testers
06/01/2010 Chile 3
06/02/2010 Chile 4
06/03/2010 Chile 0
06/04/2010 Chile 0
06/05/2010 Chile 19
but what I need right now is
Allocated testers
19
that is - only one column - one row - the max value itself... (for the (via parameters (that already exists)) selected period of dates and country)
use order and limit
ORDER BY 'people needed DESC' LIMIT 1
EDITED
as LIMIT is not exist in sql
use ORDER BY and TOP
select TOP 1 .... ORDER BY 'people needed' DESC
WITH Calendar
AS (
SELECT
CAST(#StartDate AS datetime) AS Date
UNION ALL
SELECT
DATEADD(d, 1, Date) AS Expr1
FROM
Calendar AS Calendar_1
WHERE
( DATEADD(d, 1, Date) < #EndDate )
)
SELECT TOP 1 *
FROM
(
SELECT
C.Date
,C2.Country
,COALESCE(SUM(R.[Amount of people per day needed]), 0) AS [Allocated testers]
FROM
Calendar AS C
CROSS JOIN Country AS C2
LEFT OUTER JOIN Requests AS R
ON C.Date BETWEEN R.[Start date] AND R.[End date]
AND R.CountryID = C2.CountryID
WHERE
( C2.Country = #Country )
GROUP BY
C.Date
,C2.Country
OPTION
( MAXRECURSION 0 )
) lst
ORDER BY lst.[Allocated testers] DESC
Full example following the discussion in #Salil answer..
WITH Calendar AS (SELECT CAST(#StartDate AS datetime) AS Date
UNION ALL
SELECT DATEADD(d, 1, Date) AS Expr1
FROM Calendar AS Calendar_1
WHERE (DATEADD(d, 1, Date) < #EndDate))
SELECT TOP 1 C.Date, C2.Country, COALESCE (SUM(R.[Amount of people per day needed]), 0) AS [Allocated testers]
FROM Calendar AS C CROSS JOIN
Country AS C2 LEFT OUTER JOIN
Requests AS R ON C.Date BETWEEN R.[Start date] AND R.[End date] AND R.CountryID = C2.CountryID
WHERE (C2.Country = #Country)
GROUP BY C.Date, C2.Country
ORDER BY 3 DESC
OPTION (MAXRECURSION 0)
the ORDER BY 3 means order by the 3rd field in the SELECT statement.. so if you remove the first two fields, change this accordingly..