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
Related
I am trying to Create a view where i need to put condition on year and I am trying below code but I get an error. Can someone please suggest if its possible . And the output which is required I have to use CTE only.
Error is as below : incorrect Syntax near ‘if’
Code is as below :
Declare #year varchar(20)
Set #year = ‘2022’;
With CTE as
(
If #year = ‘2022’
Begin
(
Select
#year ,
Prev_date = (select DATEADD(month, -1,GETDATE()))
)
End;
Else
Begin
(
Select #year,
Prev_date= (select DATEADD(month, -2,GETDATE()))
)
End;
)
Select *
From CTE
I'm not entirely sure what you want to achieve with your cte, but concerning the condition, you can try to put the following into your view / query / whatever:
Declare #year varchar(20)
Set #year = '2022';
SELECT [year] = #year, [prev_date] = DATEADD(month, -1 * CASE WHEN #year = '2022' THEN 1 ELSE 2 END, GETDATE())
IF, BEGIN and END are related to the procedural code, and cannot be used in this context.
Your code, without further specification, can be replaced with the following:
DECLARE #Year varchar(20);
SET #Year = '2022';
WITH CTE AS
(
SELECT Year = #year,
PrevDate = DATEADD(month, -1,GETDATE())
)
SELECT *
FROM CTE;
A note and a piece of advice: it looks (am I wrong?) that you are at the beginning of the learning. Try to keep coding guidelines for SQL Server, please. I have made some quick improvements. An example link to follow: https://blog.sqlauthority.com/2008/09/25/sql-server-guidelines-and-coding-standards/
You can use simple effective query rather than going for CTE which should be used for complex queries.
Declare #year varchar(20) Set #year = '2023';
select #year [Year], prev_date = case when #year='2022' then (Select DATEADD(month, -1,GETDATE())) else DATEADD(month, -2,GETDATE()) end
You have not give the error and what database you are using.
I suppose you sql should be syntax error, please try this
Declare #year varchar(20)
Set #year = ‘2022’
With CTE as
(
If #year = ‘2022’
Begin
{
Select
#year ,
(select DATEADD(month, -1,GETDATE())) as previous_date
}
END;
)
Select *
From CTE
BEGIN ... END; must use with {..} in the case use have multiple statments in between.
Hope this help.
I want to show all dates between two dates when there is any date data missing then its should show zero in val column .
declare #temp table (
id int identity(1,1) not null,
CDate smalldatetime ,
val int
)
INSERT STATEMENT FOR DATA TO CHECK
insert into #temp select '10/2/2012',1
insert into #temp select '10/3/2012',1
insert into #temp select '10/5/2012',1
insert into #temp select '10/7/2012',2
insert into #temp select '10/9/2012',2
insert into #temp select '10/10/2012',2
insert into #temp select '10/13/2012',2
insert into #temp select '10/15/2012',2
Retrieve records between first day of month and today
select * from #temp where CDate between '10/01/2012' AND '10/15/2012'
As i run this query its show me all data between these two dates but i want to also include missing dates with val=0
SQL FIDDLE WITH SAMPLE DATA
;with d(date) as (
select cast('10/01/2012' as datetime)
union all
select date+1
from d
where date < '10/15/2012'
)
select t.ID, d.date CDate, isnull(t.val, 0) val
from d
left join temp t
on t.CDate = d.date
order by d.date
OPTION (MAXRECURSION 0) -- use this if your dates are >99 days apart
You need to make up the dates, so I've use a recursive common table expression here.
SQL Fiddle
MAXRECURSION number
Specifies the maximum number of recursions allowed for this query. number is a nonnegative
integer between 0 and 32767. When 0 is specified, no limit is applied. If this option is
not specified, the default limit for the server is 100.
When the specified or default number for MAXRECURSION limit is reached during query
execution, the query is ended and an error is returned.
This will work as long as there are less than 2047 days between from and to dates
declare #from smalldatetime = '10/01/2012'
declare #to smalldatetime = '10/15/2012'
select t.id, dateadd(day, number,#from), isnull(val, 0) val from #temp t
right join master..spt_values s
on dateadd(d, s.number, #from) = t.CDate
where
datediff(day, #from, #to ) > s.number
and s.type = 'P'
I think the best way to do this is to create your own table with dates (you can also use master.dbo.spt_values, but I personally don't like that solution)
declare #Temp_Dates table (CDate datetime)
declare #Date datetime
select #Date = (select min(CDate) from temp)
while #Date <= (select max(CDate) from temp)
begin
insert into #Temp_Dates (CDate)
select #Date
select #Date = dateadd(dd, 1, #Date)
end
select D.CDate, isnull(T.id, 0) as id
from #Temp_Dates as D
left outer join temp as T on T.CDate = D.CDate
you can also use recursive solution with CTE
DECLARE #min DATETIME,
#max DATETIME,
#val INT
SELECT #min = Min(CDATE),
#max = Max(CDATE)
FROM TEMP
DECLARE #temp TABLE
(
CDATE SMALLDATETIME,
VAL INT
)
WHILE #min < #max
BEGIN
SELECT #val = VAL
FROM TEMP
WHERE CDATE = #min
INSERT #temp
VALUES (#min,
#val)
SET #min = Dateadd(D, 1, #min)
SET #val = 0
END
SELECT *
FROM #temp
Declare #temp Table(id int identity(1,1) not null,CDate smalldatetime ,val int)
insert into #temp select '10/2/2012',1
insert into #temp select '10/3/2012',1
insert into #temp select '10/5/2012',1
insert into #temp select '10/7/2012',2
insert into #temp select '10/9/2012',2
insert into #temp select '10/10/2012',2
insert into #temp select '10/13/2012',2
insert into #temp select '10/15/2012',2
DECLARE #startDate DATE= '10/01/2012'
DECLARE #endDate DATE= '10/15/2012'
SELECT t.Id, X.[Date],Val = COALESCE(t.val,0)
FROM
(SELECT [Date] = DATEADD(Day,Number,#startDate)
FROM master..spt_values
WHERE Type='P'
AND DATEADD(day,Number,#startDate) <= #endDate)X
LEFT JOIN #temp t
ON X.[Date] = t.CDate
using a recursive cte with min and max
declare #T table (id int identity(1,1) primary key, dt date not null, val int not null);
insert into #T (dt, val) values
('10/2/2012',1)
, ('10/3/2012',1)
, ('10/5/2012',1)
, ('10/7/2012',2)
, ('10/9/2012',2)
, ('10/10/2012',2)
, ('10/13/2012',2)
, ('10/15/2012',2);
--select * from #T;
with cte as
( select min(dt) as dt, max(dt) as mx
from #T
union all
select dateadd(dd, 1, dt), mx
from CTE
where dt < mx
)
select c.dt, isnull(t.val, 0) as val
from cte c
left join #T t
on c.dt = t.dt
order by c.dt
option (maxrecursion 0);
dt val
---------- -----------
2012-10-02 1
2012-10-03 1
2012-10-04 0
2012-10-05 1
2012-10-06 0
2012-10-07 2
2012-10-08 0
2012-10-09 2
2012-10-10 2
2012-10-11 0
2012-10-12 0
2012-10-13 2
2012-10-14 0
2012-10-15 2
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
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
I want to show all dates between two dates when there is any date data missing then its should show zero in val column .
declare #temp table (
id int identity(1,1) not null,
CDate smalldatetime ,
val int
)
INSERT STATEMENT FOR DATA TO CHECK
insert into #temp select '10/2/2012',1
insert into #temp select '10/3/2012',1
insert into #temp select '10/5/2012',1
insert into #temp select '10/7/2012',2
insert into #temp select '10/9/2012',2
insert into #temp select '10/10/2012',2
insert into #temp select '10/13/2012',2
insert into #temp select '10/15/2012',2
Retrieve records between first day of month and today
select * from #temp where CDate between '10/01/2012' AND '10/15/2012'
As i run this query its show me all data between these two dates but i want to also include missing dates with val=0
SQL FIDDLE WITH SAMPLE DATA
;with d(date) as (
select cast('10/01/2012' as datetime)
union all
select date+1
from d
where date < '10/15/2012'
)
select t.ID, d.date CDate, isnull(t.val, 0) val
from d
left join temp t
on t.CDate = d.date
order by d.date
OPTION (MAXRECURSION 0) -- use this if your dates are >99 days apart
You need to make up the dates, so I've use a recursive common table expression here.
SQL Fiddle
MAXRECURSION number
Specifies the maximum number of recursions allowed for this query. number is a nonnegative
integer between 0 and 32767. When 0 is specified, no limit is applied. If this option is
not specified, the default limit for the server is 100.
When the specified or default number for MAXRECURSION limit is reached during query
execution, the query is ended and an error is returned.
This will work as long as there are less than 2047 days between from and to dates
declare #from smalldatetime = '10/01/2012'
declare #to smalldatetime = '10/15/2012'
select t.id, dateadd(day, number,#from), isnull(val, 0) val from #temp t
right join master..spt_values s
on dateadd(d, s.number, #from) = t.CDate
where
datediff(day, #from, #to ) > s.number
and s.type = 'P'
I think the best way to do this is to create your own table with dates (you can also use master.dbo.spt_values, but I personally don't like that solution)
declare #Temp_Dates table (CDate datetime)
declare #Date datetime
select #Date = (select min(CDate) from temp)
while #Date <= (select max(CDate) from temp)
begin
insert into #Temp_Dates (CDate)
select #Date
select #Date = dateadd(dd, 1, #Date)
end
select D.CDate, isnull(T.id, 0) as id
from #Temp_Dates as D
left outer join temp as T on T.CDate = D.CDate
you can also use recursive solution with CTE
DECLARE #min DATETIME,
#max DATETIME,
#val INT
SELECT #min = Min(CDATE),
#max = Max(CDATE)
FROM TEMP
DECLARE #temp TABLE
(
CDATE SMALLDATETIME,
VAL INT
)
WHILE #min < #max
BEGIN
SELECT #val = VAL
FROM TEMP
WHERE CDATE = #min
INSERT #temp
VALUES (#min,
#val)
SET #min = Dateadd(D, 1, #min)
SET #val = 0
END
SELECT *
FROM #temp
Declare #temp Table(id int identity(1,1) not null,CDate smalldatetime ,val int)
insert into #temp select '10/2/2012',1
insert into #temp select '10/3/2012',1
insert into #temp select '10/5/2012',1
insert into #temp select '10/7/2012',2
insert into #temp select '10/9/2012',2
insert into #temp select '10/10/2012',2
insert into #temp select '10/13/2012',2
insert into #temp select '10/15/2012',2
DECLARE #startDate DATE= '10/01/2012'
DECLARE #endDate DATE= '10/15/2012'
SELECT t.Id, X.[Date],Val = COALESCE(t.val,0)
FROM
(SELECT [Date] = DATEADD(Day,Number,#startDate)
FROM master..spt_values
WHERE Type='P'
AND DATEADD(day,Number,#startDate) <= #endDate)X
LEFT JOIN #temp t
ON X.[Date] = t.CDate
using a recursive cte with min and max
declare #T table (id int identity(1,1) primary key, dt date not null, val int not null);
insert into #T (dt, val) values
('10/2/2012',1)
, ('10/3/2012',1)
, ('10/5/2012',1)
, ('10/7/2012',2)
, ('10/9/2012',2)
, ('10/10/2012',2)
, ('10/13/2012',2)
, ('10/15/2012',2);
--select * from #T;
with cte as
( select min(dt) as dt, max(dt) as mx
from #T
union all
select dateadd(dd, 1, dt), mx
from CTE
where dt < mx
)
select c.dt, isnull(t.val, 0) as val
from cte c
left join #T t
on c.dt = t.dt
order by c.dt
option (maxrecursion 0);
dt val
---------- -----------
2012-10-02 1
2012-10-03 1
2012-10-04 0
2012-10-05 1
2012-10-06 0
2012-10-07 2
2012-10-08 0
2012-10-09 2
2012-10-10 2
2012-10-11 0
2012-10-12 0
2012-10-13 2
2012-10-14 0
2012-10-15 2