Use a variable inside a conversion function - sql

I have a query that is getting a list of dates. I need each value to be within a particular month. My Completed field is a DATETIME data type, so I am cutting the time portion off. My results image shows the output from the my query.
Am I able to replace the -1 in my StartOfMonth & EndOfMonth variables with my MonthsToGoBack variable so that I only have to change its value if I want a different month?
= CONVERT(CHAR(10), DATEADD(m, #MonthsToGoBack, DATEADD(
results
DECLARE
#MonthsToGoBack INT = -1,
#StartOfMonth DATE = CONVERT(CHAR(10), DATEADD(m, -1, DATEADD(mm, DATEDIFF(m, 0, GETDATE()), 0)), 101), -- first day of the month
#EndOfMonth DATE = CONVERT(CHAR(10), DATEADD(d, -1, DATEADD(mm, DATEDIFF(m, 0, GETDATE()),0)), 101) -- last day of the month
;
SELECT DISTINCT CONVERT(VARCHAR, CompletedDate, 101) AS CompletedDate
FROM MyTable
WHERE CONVERT(DATE, CompletedDate) BETWEEN #StartOfMonth AND #EndOfMonth
I am currently seeing this error when I try it.
Msg 137, Level 15, State 2, Line 5
Must declare the scalar variable "#MonthsToGoBack".
Msg 137, Level 15, State 2, Line 19
Must declare the scalar variable "#StartOfMonth".

Don't try and do all of the logic to set the variable's value in the declaration - you can DECLARE a variable first, and then SET its value in a subsequent statement.
DECLARE
#MonthsToGoBack INT = -1,
#StartOfMonth DATE,
#EndOfMonth DATE;
SET #StartOfMonth = CONVERT(CHAR(10), DATEADD(m, #MonthsToGoBack, DATEADD(mm, DATEDIFF(m, 0, GETDATE()), 0)), 101);
Now the value of #StartOfMonth is set as you expect. You can then use the same SET command to set the appropriate value of other variables, and then use them in later statements.

Related

Can a SSRS report contain double date/time parameters?

Is it possible to have two date/time parameters in a report?
I have a simple dataset with the 'where' clause:
where RequestSource in (#reqsource)
and EntryDay between #startdate and #finishdate
and EntryDay between #periodstart and #periodend
In the report there is a calendar date/time parameter (using #startdate and #finishdate) and I wanted to add a second one (two part parameter) (using #periodstart and #periodend).
The dataset for the #periodstart parameter contains:
select DATEADD(qq, DATEDIFF(qq, 0, GETDATE()) - 1, 0) as time, 'last quarter start' as timename
union all
select DATEADD(qq, DATEDIFF(qq, 0, GETDATE()), 0) as time, 'this quarter start' as timename
union all
select DATEADD(yy, DATEDIFF(yy, 0, GETDATE()), 0) as time, 'this year start' as timename
union all
select DATEADD(yy, DATEDIFF(yy, 0, GETDATE()) - 1, 0) as time, 'last year start' as timename
The dataset #periodend parameter contains:
select DATEADD(dd, -1, DATEADD(qq, DATEDIFF(qq, 0, GETDATE()), 0)) as time, 'last quarter end' as timename
union all
select DATEADD (dd, -1, DATEADD(qq, DATEDIFF(qq, 0, GETDATE()) +1, 0)) as time, 'this quarter end' as timename
union all
select DATEADD(yy, DATEDIFF(yy, 0, GETDATE()) + 1, -1) as time, 'this year end' as timename
union all
select DATEADD(yy, DATEDIFF(yy, 0, GETDATE()), -1) as time, 'last year end' as timename
Is it possible to have the #startdate and #finishdate parameters in null and use the #periodstart and #periodend parameters which have pre-defined values?
report parameter view
I'm not really sure what your issue is, you are asking if it's possible to have more than one start date and end date?
Yes it is, you just need to accommodate this in your dataset query.
Unless I'm missing something I would do it something like this.
DECLARE #sDate datetime
DECLARE #eDate datetime
SET #sDate = ISNULL(#startdate, #periodstart)
SET #eDate = ISNULL(#finishdate, #periodend)
SELECT *
FROM myTable
WHERE RequestSource IN (#reqsource)
AND EntryDay BETWEEN #sDate AND #eDate

Loop through the same query to build historical table changing one variable

I have read only access to SQL Server 2008 and I need to build a historical table of percentages based on different points of time in the past (i.e. the last 15 months). The only value that needs to be changed is on the *** line is -0 after GETDATE()). The value needs to change -0, -1, -2...-15. I am inserting into a temp table. Any suggestions would be appreciated.
declare #enddate datetime
declare #end1195 datetime
declare #beg1195 datetime
declare #enddos datetime
declare #begdos datetime
declare #period nvarchar(7)
***set #enddate = DATEADD(MONTH, DATEDIFF(MONTH, -1, GETDATE())-0, -1)
set #end1195 = DATEADD(MONTH, DATEDIFF(MONTH, -1, (#enddate))-1, -1)
set #beg1195 = DATEADD(MONTH, DATEDIFF(MONTH, 0, dateadd(month, -6, #enddate)), 0)
set #enddos = DATEADD(MONTH, DATEDIFF(MONTH, -1, (#enddate))-0, -1)
set #begdos= DATEADD(MONTH, DATEDIFF(MONTH, 0, dateadd(month, -0, #enddate)), 0)
set #period = cast(MONTH(#enddate) as nvarchar(2)) + '-' + cast(YEAR(#enddate) as nvarchar(4))
--1195 BY Facilityid excluding ANES
insert into ##Fac1195
select
A.Facilityid, cast(1 as int) as Facility,
A.FSC_DESC, #period as Period, #begdos as DOS_Beg,
#enddos as DOS_End,
ROUND(sum(A.adjustments)/sum(A.charges), 2) as [1195]
from
(select
v.Facilityid, v.localfacility, v.VisitID, v.AccountNumber,
v.DOS, FSC.PrimayPayer as PayerName,
FSC.PrimaryCorpFSC as FSC_DESC,
chg.charges, isnull(adj.Adjustments,0) as Adjustments
........

Persistence of SQL Variables Between Statements Using SET and DECLARE in Perl's DBI

I am trying to declare/set some variables in SQL-Server using a Perl DBI statement and then use those variables in other DBI statements, but it seems like the variables are not persisting between statement calls.
$dbh->do(
q{
DECLARE #BOM1 datetime -- Beginning of Month 1 in the Quarter
DECLARE #BOM2 datetime -- Beginning of Month 2 in the Quarter
DECLARE #BOM3 datetime -- Beginning of Month 3 in the Quarter
DECLARE #EOM1 datetime -- End of Month 1 in the Quarter
DECLARE #EOM2 datetime -- End of Month 2 in the Quarter
DECLARE #EOM3 datetime -- End of Month 3 in the Quarter
SET #BOM1 = DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()) -3, 0)
SET #BOM2 = DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()) -2, 0)
SET #BOM3 = DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()) -1, 0)
SET #EOM1 = DATEADD(DAY, -1, #BOM2)
SET #EOM2 = DATEADD(DAY, -1, #BOM3)
SET #EOM3 = DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0) -1
}
);
(
$start_of_month_1,
$start_of_month_2,
$start_of_month_3,
$end_of_month_1,
$end_of_month_2,
$end_of_month_3
) = $dbh->selectrow_array(
q{
SELECT CONVERT(VARCHAR(12), #BOM1, 107),
CONVERT(VARCHAR(12), #BOM2, 107),
CONVERT(VARCHAR(12), #BOM3, 107),
CONVERT(VARCHAR(12), #EOM1, 107),
CONVERT(VARCHAR(12), #EOM2, 107),
CONVERT(VARCHAR(12), #EOM3 107)
}
);
I get the following error messages:
DBD::ODBC::db selectrow_array failed: [Microsoft][ODBC SQL Server Driver][SQL Server]Must declare the scalar variable "#BOM1". (SQL-42000)
[Microsoft][ODBC SQL Server Driver][SQL Server]Statement(s) could not be prepared. (SQL-42000)
If I merge these two statements then everything works fine, but I have many different queries that I want to run and use those declared variables. I could solve this by using the Perl variables I get back, but I wanted to know what I'm doing wrong or if it is possible to do this with the SQL variables.
Edit:
This is the connection string I am using:
"dbi:ODBC:driver={SQL Server};server=$server;database=$database;port=$port"

Prior Month for Prior Year

I have been able to Declare and Set grabbing the prior months data.
DECLARE #FirstDayofPrevMonth datetime
SET #FirstDayofPrevMonth = DATEADD(mm, DATEDIFF(m,0,GETDATE())-1,0)
DECLARE #LastDayofPrevMonth datetime
SET #LastDayofPrevMonth = DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,GETDATE()),0))
What I now need is to be able to set and declare prior month, prior year....
to be clear, this does work for me. I get the expected result which is Aug 2014. What I'm looking to do, is get Aug 2013 and so on.
UPDATE:
I thought I would share two other pieces I added to my code that may be helpful to others.
I used the below answer and added to it
DECLARE #FirstDayofPrevMonth datetime
SET #FirstDayofPrevMonth = DATEADD(mm, DATEDIFF(m,0,GETDATE())-1,0)
DECLARE #LastDayofPrevMonth datetime
SET #LastDayofPrevMonth = DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,GETDATE()),0))
-- to be used for the prior year completed month
DECLARE #FirstDayofPrevMonthLY datetime
SET #FirstDayofPrevMonthLY = DATEADD(year,-1,#FirstDayofPrevMonth)
DECLARE #LastDayofPrevMonthLY datetime
SET #LastDayofPrevMonthLY = DATEADD(year,-1,#LastDayofPrevMonth)
--This is to be used if you want for dates in the current Quarter
DECLARE #FirstDayofCQ datetime
SET #FirstDayofCQ = DATEADD(qq, DATEDIFF(qq, 0, GETDATE()), 0)
DECLARE #LastDayofCQ datetime
SET #LastDayofCQ =DATEADD(qq, DATEDIFF(qq, 0, GETDATE()) + 1, 0)
--This is to be used for the Prior Quarter
DECLARE #FirstDayofPrevQ datetime
SET #FirstDayofPrevQ = DATEADD(qq, DATEDIFF(qq, 0, GETDATE()) - 1, 0)
DECLARE #LastDayofPrevQ datetime
SET #LastDayofPrevQ = DATEADD(dd, -1, DATEADD(qq, DATEDIFF(qq, 0, GETDATE()), 0))
DECLARE #FirstDayofPrevMonthPriorYear datetime
DECLARE #LastDayofPrevMonthPriorYear datetime
SET #FirstDayofPrevMonthPriorYear = DATEADD(year,-1,#FirstDayofPrevMonth)
SET #LastDayofPrevMonthPriorYear = DATEADD(year,-1,#LastDayofPrevMonth)
DECLARE #FirstDayofPrevMonthPrevYear datetime
SET #FirstDayofPrevMonthPrevYear = (DATEADD(yy, -1, DATEADD(mm, DATEDIFF(m,0,GETDATE())-1,0)))

SQL Query for YTD, MTD, WTD totals

I would like this query to be able to automagically know today's date & time as well as the first of the year (or month) (or week)...
SELECT TicketID
FROM Ticket
WHERE (Ticket.DtCheckOut > '1/1/2011 12:00:00 AM')
AND (Ticket.DtCheckOut < '8/27/2011 12:00:00 AM')
I know it will use GETDATE() in some form, but you don't want to see what I've come up with, I promise!
Here is what I was reading on GETDATE() MDSN: GETDATE(Transact-SQL)
I looked around here and Google - and didn't find anything 'clean' - so any input would be awesome!
DECLARE #now DATETIME
SET #now = GETDATE()
SELECT
DATEADD(yy, DATEDIFF(yy, 0, #now), 0) AS FirstDayOfYear,
DATEADD(mm, DATEDIFF(mm, 0, #now), 0) AS FirstDayOfMonth,
DATEADD(DAY, -DATEDIFF(dd, ##DATEFIRST - 1, #now) % 7, #now) AS FirstDayOfWeek
##DATEFIRST is SQL Server's first day of the week, which defaults to Sunday if you are using U.S. English.
For the first day of the week it can be a bit tricky, depending on your actual requirements (whether you want to obey the user's datefirst setting or not, use Sunday regardless of the setting, etc.), see this question: Get first day of week in SQL Server. Here is one way to do it:
DECLARE
#today DATE = CURRENT_TIMESTAMP,
#y DATE,
#m DATE,
#w DATE;
SELECT
#y = DATEADD(YEAR, DATEDIFF(YEAR, 0, #today), 0),
#m = DATEADD(MONTH, DATEDIFF(MONTH, 0, #today), 0),
#w = DATEADD(DAY, 1-DATEPART(WEEKDAY, #today), #today);
SELECT
[First day of year] = #y,
[First day of month] = #m,
[First day of week] = #w;
Whichever one you are after, you can use in the query, e.g. for YTD you would use:
SELECT TicketCount = COUNT(TicketID)
FROM dbo.Ticket
WHERE DtCheckOut >= #y;
Don't really think you need the < portion of the query if you're trying to get a count up to right now. How many tickets will have been checked out tomorrow if I'm running the query today? If you want to protect yourself against that you can use:
SELECT COUNT(TicketID)
FROM dbo.Ticket
WHERE DtCheckOut >= #y
AND DtCheckOut < DATEADD(DAY, 1, #now);
You could make it a little more dynamic and pass in a parameter that says 'YTD', 'MTD' or 'WTD', e.g.
CREATE PROCEDURE dbo.CountTickets
#Range CHAR(3) = 'YTD'
AS
BEGIN
SET NOCOUNT ON;
-- you may want to handle invalid ranges, e.g.
IF #Range NOT IN ('YTD', 'MTD', 'WTD')
BEGIN
RAISERROR('Please enter a valid range.', 11, 1);
RETURN;
END
DECLARE
#today DATE = CURRENT_TIMESTAMP,
#start DATE;
SELECT
#start = CASE #range
WHEN 'YTD' THEN DATEADD(YEAR, DATEDIFF(YEAR, 0, #today), 0)
WHEN 'MTD' THEN DATEADD(MONTH, DATEDIFF(MONTH, 0, #today), 0)
WHEN 'WTD' THEN DATEADD(DAY, 1-DATEPART(WEEKDAY, #today), #today)
END;
SELECT
Range = #range,
TicketCount = COUNT(TicketID)
FROM dbo.Ticket
WHERE dtCheckOUt >= #start;
END
GO