Using an Aggregate function with a sub query - sql

We get a new batch of widgets each month. We know the product codes of these widgets which will be is stock, waiting to be used. Each also has an availability date, after which it can be used.
Table WidgetStock
Columns: WidgetID, AvailabilityDate,
Another table has the uses of the widget, ie when it was first used.
Table WidgetsUsed
Columns: datetime, Operator
I'd like to see by day and hour the amount of fresh widgets that I have used for the first time, since the start of the month. The widgets will be used multiple times, so a simple distinct count by hour is not really enough, as widgets would be double counted.
In my mind this would require looking at a list of available numbers, which is updated for each line of a group by query.
The below query will not work, but hopefully it shows what I am trying to achieve:
declare #StartofMonth datetime
set #StartofMonth = '20160901'
select CONVERT(varchar, wu.datetime, 103)'Date'
, convert(char(2), wu.datetime, 108)'Hour'
--Problem Line below
, SUM(case when wu.StockNo in (select ba.NUMBER
from widgetStock ba
where availability_date between CONVERT(varchar, wu.datetime, 103) and #StartofMonth) then 1 else 0 end) 'Number Used'
from widgetsUsed wu
left join widgetStock ws on wu.StockNo = ws.NUMBER
where wu.OPERATOR = 'WidgetWorld'
and DATETIME between '20160914' and '20160916'
group by CONVERT(varchar,wu.datetime,103), convert(char(2), wu.datetime, 108)
Any help with this is appreciated. Thanks in advance.

If understood your requirement then below script may solve your problem
declare #StartofMonth datetime
set #StartofMonth = '20160901'
select CONVERT(varchar, wu.datetime, 103)'Date'
, convert(char(2), wu.datetime, 108)'Hour'
, SUM(ISNULL(ba.NUMBER,0)) 'Number Used'
from widgetsUsed wu
left join widgetStock ws on wu.StockNo = ws.NUMBER
LEFT JOIN widgetStock ba ON wu.StockNo = ba.NUMBER AND availability_date between CONVERT(varchar, wu.datetime, 103) and #StartofMonth
where wu.OPERATOR = 'WidgetWorld'
and DATETIME between '20160914' and '20160916'
group by CONVERT(varchar,wu.datetime,103), convert(char(2), wu.datetime, 108)

Related

sql with group by and range of dates

I have a query which uses max aggregate function to calculate reset date for a particular selection date.There is a table vp_Accrual which have effectivedate field.selection date is passed to effectivedate field and based on that using Max function, reset date is calculated.This Query gives result only for a particular selection date.It calculate a reset date based on selection date passed.
I want to modify it so that it will give me reset date for a range of dates
Below Query gives Output for one person for the date 1st Jan as follow.
We need to modify Query so that it will give result for multiple selection date instead of only one selection date.
I tried by adding addition #enddate field as effectivedate between #selectiondate and #enddate.
But I guess tha approach is not correct.
I want to pass range of date, such as 1st jan to 4th Jan, and it should give Output for each date as below
[Image is added as Link as i dont have enough Repuation Point][https://i.stack.imgur.com/0HSX1.jpg]
Below is the Query used.
DECLARE #selectionDate datetime
SET #selectionDate = CONVERT(nvarchar(10), DATEADD(dd, 0, CAST('01/01/2017' AS datetime)), 101)
SELECT
e.personnum,
ac.name as Accrul_Code,
#selectionDate as Selection_DATE,
CASE
WHEN MAX(va.effectivedate) IS NULL THEN CAST('1/1/1753' AS datetime)
ELSE MAX(va.effectivedate)
END AS resetdate
FROM vp_employeev42 e WITH (NOLOCK)
INNER JOIN accrualprofile ap
ON e.accrualprflname = ap.name
INNER JOIN accrualprofilemm apm
ON apm.accrualprofileid = ap.accrualprofileid
INNER JOIN accrualrule ar
ON apm.accrualruleid = ar.accrualruleid
INNER JOIN accrualcode ac
ON ac.accrualcodeid = ar.accrualcodeid
LEFT OUTER JOIN vp_accrual va
ON va.accrualcodeid = ar.accrualcodeid
AND e.personid = va.personid
AND accrualtrantype IN (3, 11)
AND va.effectivedate <= #selectionDate
WHERE
ac.NAME IN ('FT PTO','LOC','EPT - 5','PT PTO','EPT')
AND va.DISQUALIFIEDSW != 1
and e.PERSONNUM='00152'
GROUP BY e.personnum,
ac.name
Please help me with this Query
Best I can make out, you want a Cartesian join on a fake date table that will cause your results to repeat themselves over and over, but for a different set of dates each time
Something like this:
DECLARE #selectionDate datetime
DECLARE #endDate datetime
SET #selectionDate = DATEFROMPARTS(2017,1,1)
SET #endDate = DATEFROMPARTS(2017,5,1)
WITH dates ( IncDate ) AS (
SELECT #selectionDate UNION ALL
SELECT DATEADD(month,1,IncDate) FROM dates WHERE Incdate <= #endDate )
SELECT
e.personnum,
ac.name as Accrul_Code,
IncDate as Selection_DATE,
MAX(COALESCE(effectivedate, CAST('1/1/1753' AS datetime)) AS resetdate
FROM vp_employeev42 e WITH (NOLOCK)
INNER JOIN accrualprofile ap
ON e.accrualprflname = ap.name
INNER JOIN accrualprofilemm apm
ON apm.accrualprofileid = ap.accrualprofileid
INNER JOIN accrualrule ar
ON apm.accrualruleid = ar.accrualruleid
INNER JOIN accrualcode ac
ON ac.accrualcodeid = ar.accrualcodeid
CROSS JOIN dates
LEFT OUTER JOIN vp_accrual va
ON va.accrualcodeid = ar.accrualcodeid
AND e.personid = va.personid
AND accrualtrantype IN (3, 11)
AND effectivedate <= IncDate
WHERE
ac.NAME IN ('FT PTO','LOC','EPT - 5','PT PTO','EPT')
AND va.DISQUALIFIEDSW != 1
and e.PERSONNUM='00152'
GROUP BY e.personnum,
ac.name,
IncDate
A few cautions though:
This query cannot generate the results you posted, but neither can yours. There's no logic at all to your example results, where your reset date is the max date that is less than the selection date but your first of February selection date somehow chooses the tenth of Jan, yet your first of march selection date chooses the eleventh of Jan.
This is totally untested; you provided no sample data, only an image of the results, and I post from an iPad, so generating test data would be incredibly laborious, typing it all in
You mix up your dates as varchar and datetime. Please be more diligent in keeping these data types separate. Always work with dates as dates, not strings. Never store dates as string. Never rely on implicit conversions between date and string
DATEFROMPARTS came along in sqlserver 2012 I think, if your sql is older than this, use convert with a format string to turn your string into a date.. do not declare selectiondate as a varchar!

How to get week formatted string in sql query

I have the following SQL query (sql server 2008):
SELECT sum(data.freq) as freq,data.week as week FROM (
SELECT
count(daterequested) as freq,
datepart(wk,daterequested) as week,
daterequested
FROM request ma
JOIN contracts mc ON (mc.uid= ma.uid)
JOIN groups og ON og.groupuid = mc.groupuid
JOIN member m ON (m.memberuid = mc.memberuid)
WHERE daterequested BETWEEN
DATEADD(MONTH,-1,GETDATE())
AND
GETDATE()
AND isdeleted = 0
GROUP BY datepart(wk,daterequested),daterequested
--ORDER BY daterequested ASC
) data
GROUP BY data.week
The result is a table with the following data:
Instead of showing the week number I would like to show the week formatted as following:
MM/dd where MM = month and dd is the day where the week starts.
It would be great if I can format starting with first day of the week, then a middle slash, then the last day of that week and finally the month: example: 11-17/04 (April 11 to 17), etc.
Here is the final table that I would like to get:
Any clue?
In case someone needs it just found a solution, maybe is not the best but works.
SELECT sum(data.freq) as freq,
data.week as week, CAST(data.weekstart as varchar) + '-' + CAST(data.weekend as varchar) + '/' + CAST(data.monthend as varchar) as formatweek
FROM (
SELECT
count(daterequested) as freq,
datepart(wk,daterequested) as week,
DATEPART(dd,DATEADD(dd, -(DATEPART(dw, daterequested)-1), daterequested)) weekstart,
DATEPART(dd,DATEADD(dd, 7-(DATEPART(dw, daterequested)), daterequested)) weekend,
DATEPART(mm,DATEADD(dd, 7-(DATEPART(dw, daterequested)), daterequested)) monthend,
daterequested
FROM requestma
JOIN contracts mc ON (mc.uid= ma.uid)
JOIN groups og ON og.groupuid = mc.groupuid
JOIN member m ON (m.memberuid = mc.memberuid)
WHERE daterequested BETWEEN
DATEADD(MONTH,-1,GETDATE())
AND
GETDATE()
AND isdeleted = 0
GROUP BY datepart(wk,daterequested),daterequested
--ORDER BY daterequested ASC
) data
GROUP BY data.week,data.weekstart,data.weekend,data.monthend

I have two tables with common Quote_No and I need to sum Qty in Quote_Items with Required by Date in Table Quotes

I am trying to get the sum of "Qty" in a Table A called "Quote_Items" based on a "Required_by_Date" from Table B called Quotes. Both tables have a common "Quote_No" The required date is one month ago.
I have used the following but it produces a NULL, but I cannot see why
select sum(Qty)
from quotes.Quote_Items_Quantities
left outer join quotes.Quotes on (Quote_Required_by_Date = Qty)
WHERE (DatePart(yy, Quote_Required_by_Date) = DatePart(yy, DateAdd(m,1,getdate()))) and
datepart(m,Quote_Required_by_Date) = datepart(m,dateadd(m,1,getdate()))
Any suggestions what I am doing wrong here.
Try this:
SELECT SUM(i.Qty)
FROM Quote_Items i
JOIN Quotes q on i.Quote_No = q.Quote_No
AND CONVERT(varchar, q.Required_by_Date, 112) = CONVERT(varchar, DATEADD(month, -1, getdate()), 112)
or this (equivalent without using JOIN)
SELECT SUM(i.Qty)
FROM Quote_Items i
WHERE EXISTS(SELECT 1 FROM Quotes WHERE Quote_No = i.Quote_No AND CONVERT(varchar, Required_by_Date, 112) = CONVERT(varchar, DATEADD(month, -1, getdate()), 112))
Your query is producing NULL because of the join condition. You have
on Quote_Required_by_Date = Qty
However, the date is not going to match the quantity. Instead, you need to match on the Quote_No, according to your question:
select sum(Qty)
from quotes.Quote_Items_Quantities qiq left outer join
quotes.Quotes q
on q.Quote_Required_by_Date = qiq.Qty
WHERE (DatePart(yy, Quote_Required_by_Date) = DatePart(yy, DateAdd(m,1,getdate()))) and
datepart(m,Quote_Required_by_Date) = datepart(m,dateadd(m,1,getdate()));
You can also simplify your query by using the month() and year() functions:
select sum(Qty)
from quotes.Quote_Items_Quantities qiq left outer join
quotes.Quotes q
on q.Quote_Required_by_Date = qiq.Qty
WHERE year(Quote_Required_by_Date) = year(DateAdd(m, 1, getdate()) and
month(Quote_Required_by_Date) = month(dateadd(m,1,getdate());
Finally, you mind find it useful to use group by and get the results for many months:
select year(Quote_Required_by_Date), month(Quote_Required_by_Date), sum(Qty)
from quotes.Quote_Items_Quantities qiq left outer join
quotes.Quotes q
on q.Quote_Required_by_Date = qiq.Qty
group by year(Quote_Required_by_Date), month(Quote_Required_by_Date)
order by 1 desc, 2 desc;

Is it possible to have multiple parameters within a Report

I have a parameter called Reporting Level in my Report where you can choose from 4 options:
Company
BDM
Region
Site
What I want to be able to do is this:
Select BDM and this opens another Parameter call BDM List (This is based on Get Values from a query), but I want the other Parameters to stay greyed out. Once a selection is made from the BDM List then the Time and Date Parameter becomes available.
Is this possible?
These are my Datasets for the BDM List and Region List:
SELECT SiteInfo FROM
((SELECT DISTINCT BDM, Region, SiteName As SiteInfo
FROM Site
WHERE #ReportingLevel = 'BDM'
union all
SELECT DISTINCT BDM, Region, SiteName As SiteInfo
FROM Site
WHERE #ReportingLevel = 'Region' )
union all
SELECT DISTINCT BDM, Region, SiteName As SiteInfo
FROM Site
WHERE #ReportingLevel = 'SiteName') AS QRY2
This is my main Dataset:
SELECT OccupancyDetail.CalendarYear, OccupancyDetail.CalendarMonth, SUM(OccupancyDetail.No_of_Nights) AS No_of_Nights,
SUM(OccupancyDetail.Capacity) AS Capacity
FROM OccupancyDetail INNER JOIN
Site ON OccupancyDetail.Site_Skey = Site.Site_Skey
WHERE (OccupancyDetail.ReferenceDate = convert(Date,getdate()))
AND CASE WHEN #Time = 'YEAR' THEN CAST(CalendarYear as varchar(4)) else CalendarMonth + ' ' + CAST(CalendarYear as varchar(4)) end in (#Dates)
AND Site.BDM IN (#BDM)
AND Site.Region IN (#Region)
AND Site.SiteName IN (#SiteName)
GROUP BY OccupancyDetail.ReferenceDate, OccupancyDetail.CalendarYear, OccupancyDetail.CalendarMonth
Time Dataset
select DateChoice FROM
(select distinct CalendarYear, 1 as MonthNumber,CAST(CalendarYear as varchar(4)) as DateChoice from Time
where #Time = 'YEAR'
union all
select Distinct CalendarYear, MonthNumber,CalendarMonth + ' ' + CAST(CalendarYear as varchar(4)) as DateChoice from Time where #Time = 'MONTH') as QRYDATA
ORDER BY CalendarYear,MonthNumber
I hope you can help this is my 3rd day working on this.
Thanks
Wayne
I believe you are looking to use cascading parameters, here are a few links that should help you.
http://technet.microsoft.com/en-us/library/dd255197.aspx
http://thevirtualzoneblog.wordpress.com/2011/03/30/creating-cascading-parameter-reports-using-sql-server-reporting-services-v2008/
With the first link, go to the section marked 'To create a dataset to provide values for a dependent parameter'. This next one shows the parameters as greyed out before the parent has an option selected:
http://www.resultdata.com/adding-cascading-parameters-to-a-ssrs-report/
Update
I have found a video tutorial for you:
http://www.youtube.com/watch?v=VAYGupJcHkU

I need help displaying a field that is zero

In this query I'm counting work orders that were created the previous week and displaying a count by wotype2. If a wotype2 for the previous week is zero, I need the wotype2 to appear in my results. Any ideas on how to pull this off?
-- Retrieve Last Week's New Work Orders.
DECLARE #TodayDayOfWeek INT
DECLARE #EndOfPrevWeek DateTime
DECLARE #StartOfPrevWeek DateTime
--get number of a current day (1-Monday, 2-Tuesday... 7-Sunday)
SET #TodayDayOfWeek = datepart(dw, GetDate())
--get the last day of the previous week (last Sunday)
SET #EndOfPrevWeek = DATEADD(dd, -#TodayDayOfWeek, GetDate())
--get the first day of the previous week (the Monday before last)
SET #StartOfPrevWeek = DATEADD(dd, -(#TodayDayOfWeek+6), GetDate())
SELECT wotype2 as WOType, COUNT(*) as NewWOsLastWeek
FROM tasks
WHERE ((OpenDATE BETWEEN
CONVERT(VARCHAR, #StartOfPrevWeek,7) AND
CONVERT(VARCHAR, #EndOfPrevWeek+1,7)) AND
(TYPE = 'Information Systems') AND
(RESPONS != 'ADMIN'))
group by wotype2
order by wotype2
You may need to do an outer join (say a left outer join) with a table which has all the possible values of wotype2.
If there is such a table, let's say it's named wotype2s, then the SQL would be:
SELECT wotype2s.wotype2 as WOType, COUNT(*) as NewWOsLastWeek
FROM wotype2s left outer join tasks on wotype2s.wotype2 = tasks.wotype2
WHERE ((OpenDATE BETWEEN
CONVERT(VARCHAR, #StartOfPrevWeek,7) AND
CONVERT(VARCHAR, #EndOfPrevWeek+1,7)) AND
(TYPE = 'Information Systems') AND
(RESPONS != 'ADMIN'))
group by wotype2s.wotype2
order by wotype2s.wotype2
or, if there is no such table,
SELECT wotype2s.wotype2 as WOType, COUNT(*) as NewWOsLastWeek
FROM (select distinct wotype2 from tasks) wotype2s
left outer join tasks on wotype2s.wotype2 = tasks.wotype2
WHERE ((OpenDATE BETWEEN
CONVERT(VARCHAR, #StartOfPrevWeek,7) AND
CONVERT(VARCHAR, #EndOfPrevWeek+1,7)) AND
(TYPE = 'Information Systems') AND
(RESPONS != 'ADMIN'))
group by wotype2s.wotype2
order by wotype2s.wotype2