If someone can help me with this, I will appreciate it.
I have 2 tables in sql 2008:
[users]
[userId] uniqueidentifier
[beginningDate] datetime
and [items]
[userId] uniqueidentifier
[itemDate] datetime
I want to count the number of users that have at least one item in [items] from January to December of any given year, I do this:
DECLARE #Year int = 2014, #Month int = 1 --January
SELECT ISNULL(Count(*), 0)
FROM [users]
WHERE
(
SELECT ISNULL(Count(*), 0) FROM [items]
WHERE [users].[userId] = [items].[userId]
AND YEAR([itemDate]) = #Year
AND ( MONTH([itemDate]) >= #Month AND MONTH([itemDate]) <= 12 )
) > 0
It works fine, the problem is that I want to check (and change accordingly), if the [beginningDate] is newer than #Month /#Year (it will always be the same year) then change the #Month variable to the [beginningDate] month value.
Thank to Allan S. Hansen for his reply.
I solved the problem by creating a function and calling it from my query:
CREATE FUNCTION [dbo].[GetMonth]
(
#UserId uniqueidentifier
, #Year int
)
RETURNS int
AS
BEGIN
DECLARE #Month int = 1; --January
DECLARE #DateValue DateTime
DECLARE #DateFrom DateTime = CONVERT(nvarchar(4), #Year) +'-03-01' --de mar
SELECT #DateValue =
CASE
WHEN [beginningDate] > #DateFrom THEN [beginningDate]
ELSE #DateFrom
END
FROM [users]
WHERE [userId] = #UserId
IF(#DateValue IS NULL)
SET #Month = 1;
ELSE
IF(#DateValue > #DateFrom) SET #Month = MONTH(#DateValue)
return #Month;
END
This is the new query:
DECLARE #Year int = 2014, #Month int = 1 --January
SELECT ISNULL(Count(*), 0)
FROM [users]
WHERE
(
SELECT ISNULL(Count(*), 0) FROM [items]
WHERE [users].[userId] = [items].[userId]
AND YEAR([itemDate]) = #Year
AND ( MONTH([itemDate]) >= [dbo].[GetMonth] ([users].[userId], #Year)
AND MONTH([itemDate]) <= 12 )
) > 0
Thanks anyway to all
Saludos
rubenc
Related
actually the function does not work properly after many tests
for example I've triedSelect * from [dbo].[fn_GetLeaveDays] ('2020-09-24',1,'2020-09-25',1,1,1)
and it should returns only 1 as friday is weekend but it returns 2
could you please assist to find whats wrong in the function
ALTER FUNCTION [dbo].[fn_GetLeaveDays] (#DateFrom datetime2,
#CalendarFunction int,
#DateTo AS datetime2,
#AdjustMode bit,
#AdjustWeekEnds bit,
#AdjustHolidays bit)
RETURNS #tbl table (totaldays int)
AS
BEGIN
IF #DateFrom > #DateTo
BEGIN
DECLARE #T datetime2 = #DateTo,
#F datetime2 = #DateFrom;
SELECT #DateFrom = #T,
#DateTo = #F;
END;
DECLARE #Count AS int = 0,
#Date AS datetime2 = #DateFrom;
WHILE #Date < #DateTo
BEGIN
IF ((DATEPART(WEEKDAY, #Date) IN (6)
AND #AdjustWeekEnds = 1)
OR EXISTS (SELECT *
FROM [C3DCalendar].[dbo].[PRIMAVERA_CALENDAR_HOLIDAYS]
WHERE holiday_date = #Date
AND calendar_key = #CalendarFunction
AND #AdjustHolidays = 1))
BEGIN
SELECT #Count = #Count + 1;
END;
SELECT #Date = DATEADD(DAY, 1, #Date);
END;
INSERT INTO #tbl
SELECT (DATEDIFF(DAY, #DateFrom, #DateTo) - (#Count)) + #AdjustMode;
RETURN;
END;
I know that there are other posts with code that solve my problem but I don't want to take another's code so I'm trying to do it by myself and I'm stuck with the month not increasing problem, so if anyone can help me with that mistake it will be awesome.
The problem is:
I have to populate the table Time from year 1990 to 2016 with all the months and days, I have already achieved that the code works and it populates correctly the years and the days but months increases to January (1) and then is not increasing so the table is filled with all months being January (LOL)
Here's my code:
create table Time
(
Year int,
Month int,
Day int
)
create procedure pTime
as
declare #year int, #month int, #day int;
set #year = 1990;
set #month = 12;
set #day = 10;
while(#year<=2016)
Begin
If(#day = 29)
Begin
set #month = #month + 1;
If(#month = 13)
Begin
set #month = 1;
set #day = 1;
set #year = #year + 1;
insert into Time values (#year, #month, #day);
End
End
else
Begin
If(#day = 29)
Begin
set #month = #month + 1;
set #day = 1;
insert into Time values (#year, #month, #day);
End
Else
Begin
insert into Time values (#year, #month, #day);
set #day = #day + 1;
End
End
End
Any idea where is my mistake or any suggestion?
I didn't look very closely for your mistake because SQL Server has some helpful date arithmetic functions. Here's simplified version of your stored procedure:
create procedure pTime
as
declare #theDate date = '12/10/1990', #days int = 0
while #theDate < '1/1/2016'
begin
insert into Time (Year, Month, Day) values (datepart(year, #theDate), datepart(month, #theDate), datepart(day, #theDate));
set #theDate = dateadd(day, 1, #theDate)
end
Another faster approach would be to use a tally table. Note the code below:
WITH
E(N) AS (SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
SELECT 1 UNION ALL SELECT 1),
iTally(N) AS (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 1))-1 FROM E a,E b,E c,E d,E e),
dates(dt) AS
(
SELECT TOP(datediff(DAY,'19900101','20160101')) DATEADD(day,N,'19900101')
FROM iTally
)
--INSERT [time] --uncomment for the insert, leave commented to see what will be inserted
SELECT YEAR(dt), MONTH(dt), DAY(dt)
FROM dates;
Why do you need If(#year = 29) condition? In your code this block never will be executed. try this:
create procedure pTime
as
declare #year int, #month int, #day int;
set #year = 1990;
set #month = 12;
set #day = 10;
while(#year<=2016)
Begin
If(#day = 29)
Begin
set #month = #month + 1;
set #day = 1;
If(#month = 13)
Begin
set #month = 1;
set #year = #year + 1;
insert into Time values (#year, #month, #day);
End
End
else
Begin
If(#day = 29)
Begin
set #month = #month + 1;
set #day = 1;
insert into Time values (#year, #month, #day);
End
Else
Begin
insert into Time values (#year, #month, #day);
set #day = #day + 1;
End
End
End
I think first assignment set #day = 1; wasn't in right place. After increasing #month value you should set also #day to 1;
I've been stuck for the past two days execute it give the error:
The data types varchar and int are incompatible in the concat operator
Here is my table:
create table salestable
(
id int identity(1,1) not null primary key,
empid char(5),
datesold date,
monthonly varchar(50),
amount money
)
This code inserts the dummy record into dbo.salestable for working in salestable, debug and step into the code that give the debug and understanding code
declare #outercounter int = 1
declare #innercounter int = 1
while #outercounter <= (select count(name) from namestable)
begin
while #innercounter <= datediff(day, getdate() -datepart(day, getdate()), {fn concat('12/31/',Datepart(year,getdate()))})
begin
insert into salestable (empid, datesold, monthonly, amount)
values (#outercounter,
getdate() - datepart(day, getdate()) + #innercounter,
Datename(month, getdate() - datepart(day, getdate()) + #innercounter),
rand() * 10000)
set #innercounter = #innercounter +1
end
set #outercounter = #outercounter + 1
set #innercounter = 1
end
select * from dbo.salestable
fn concat('12/31/',CAST(Datepart(year,getdate()) AS VARCHAR(10)))
Try this
Declare int #NumberofPriorYears=2;
Declare int #currentYear=2014;
SELECT
*
FROM
MyTable a
WHERE
a.FiscalYear in (
When #NumberofPriorYears is 2 then i want to pass #currentYear-#NumberofPriorYears (i.e 2014,2013,2012)
or when #NumberofPriorYears is null then pass #currentYear i.e 2014.
Appreciate any help on this.
Can you use a range?
a.FiscalYear >= #currentYear-isnull(#NumberofPriorYears,0)
and a.FiscalYear < #currentYear+1
Try this
Declare int #numberofyears=2;
Declare int #currentYear=2014;
set #currentYear = datepart(year,getdate())
SELECT
*
FROM
MyTable a
WHERE
datepart(year,a.FiscalYear) between #currentYear and #currentYear+#numberofYears
Declare int #numberofyears=2;
Declare int #currentYear=2014;
SELECT *
FROM MyTable a
WHERE
( YEAR(a.FiscalYear) >= YEAR(GETDATE()) - #numberofyears
AND
#numberofyears IS NOT NULL
)
OR
( YEAR(a.FiscalYear) = YEAR(GETDATE())
AND
#numberofyears IS NULL
)
SELECT *
FROM MyTable a
WHERE #currentYear - a.FiscalYear <= ISNULL(#numberOfPriorYears, 0)
If you want to be able to pass in a previous year instead of just the current year (e.g. see 2011-2012 instead of 2011-2014) you can use BETWEEN
WHERE a.FiscalYear BETWEEN #currentYear - ISNULL(#numberOfPriorYears, 0) AND #currentYear
I am using SQL Server 2008 R2.
I do have a stored procedure in which I am passing two parameters - Month and Year. By default both are NULL.
The logic is if Month and Year are NULL then fetch the previous month's records from the table. For example, today is March 5, 2014, if Month and Year are passed as NULL then stored procedure will return records of previous Month i.e. February 1st, 2014 to February 28, 2014.
And if I pass specific Month and Year then it will fetch records of that Month and Year from the table.
The stored procedure is as below :
CREATE PROCEDURE [dbo].[Proc_SalesRecords] (#Month INT = NULL, #year INT = NULL)
AS
BEGIN
DECLARE #dtnow DATETIME = GETDATE()
IF #Month IS NULL
SELECT #Month = MONTH(DATEADD(MONTH, -1, #dtnow ))
IF #Year IS NULL
SELECT #year = YEAR(DATEADD(MONTH, -1, #dtnow ))
SELECT * FROM SalesRecords
WHERE
ISNULL(#Month, MONTH(CreatedDate)) = MONTH(CreatedDate)
AND ISNULL(#year, YEAR(CreatedDate)) = YEAR(CreatedDate)
AND IsDeleted=0
END
GO
Now, I got new requirement to pass a new parameter Day to the same procedure i.e. #Day INT = NULL.
If Day is set to NULL then procedure should run as it is. But if #Day is not null then I need to fetch records for that day of the month in the previous month to one day less in this month.
For example if #Day = 22, #Month = null, #year = null, (and today is March 22th, 2014) it would fetch data for February 22nd - March 21st 2014.
Please let me now what changes should I do for this optional parameter in above given stored procedure and set the date range according to it?
Thanks
Check this:
Declare #Day int = 22
Declare #lastMonthDate dateTime, #FromDate datetime, #ToDate datetime
Set #lastMonthDate=dateadd (M, -1, GETDATE());
Set #FromDate=Convert(date, convert(varchar,Year(#lastMonthDate)) + '-' + convert(varchar,MONTH(#lastMonthDate)) + '-' + convert(varchar, #Day) )
set #ToDate = Dateadd(M,1,#FromDate)-1
select #FromDate, #Todate
May this help
CREATE PROCEDURE [dbo].[Proc_SalesRecords] (#Day INT = NULL, #Month INT = NULL, #year INT = NULL)
AS
BEGIN
DECLARE #dtnow DATETIME = GETDATE()
IF #Month IS NULL
SELECT #Month = MONTH(DATEADD(MONTH, -1, #dtnow ))
IF #Year IS NULL
SELECT #year = YEAR(DATEADD(MONTH, -1, #dtnow ))
SELECT * FROM SalesRecords
WHERE
ISNULL(#Month, MONTH(CreatedDate)) = MONTH(CreatedDate)
AND ISNULL(#year, YEAR(CreatedDate)) = YEAR(CreatedDate)
AND ((DAY(CreatedDate) BETWEEN ISNULL(#Day, DAY(CreatedDate)) AND DAY(DATEADD(DAY,-1,#dtnow))) OR (#Day IS NULL))
AND IsDeleted=0
END
GO