my source table column is ReportingPeriod Nvarchar(6)
delete query has to be for datas before 2 years.
this query does not work
delete from table where ReportingPeriod < year(getdate() -2) and month as 12
I need to get 201212 as result
the criteria is current year -2 and month is 12
in 2014 expected result is 201212
in 2015 expected result is 201312
I would do all of the date maths first keeping things as datetime and then convert to nvarchar at the end. Handily, CONVERT will just truncate the result if not enough space is provided, so we just provide space for the year and month and we get what we want:
select CONVERT(nvarchar(6),
DATEADD(year,DATEDIFF(year,'20010101',CURRENT_TIMESTAMP)
,'19991201')
,112)
Result:
201212
This works because we exploit the relationship between two arbitrary dates - for instance, for any date in 2001, the result we would want would be a date in december 1999 - so that's what I've used.
It's true that the above may look overly complex for this requirement, but it's possible to make a great many problems fit the DATEADD/DATEDIFF pattern with the appropriate choice of the period to use and the two arbitrary dates and the relationship between them.
You could try something like
SELECT FROM <YOUR_TABLE>
WHERE ReportingPeriod < Convert(nvarchar(4), year(getdate()) - 2) + '12'
You could cast your ReportingPeriod to a date, so 201212 would become 2012-12-01 as I assume you aren't concerned with the day of the month.
cast(left(ReportingPeriod,4) + '-'
+ RIGHT(ReportingPeriod, 2) + '-01' as datetime)
Then take the current year -2 from GETDATE() and append the month 12 and day 31 to compare these values against, which would return 2012-12-31.
cast(cast(
cast(year(getdate()) -2 as nvarchar(4))
+ '-12-31' as nvarchar(10)) as datetime)
So combining these you should be able to select all records older than 2 years, based on the month being set to 12.
select cast(left(ReportingPeriod,4) + '-'
+ RIGHT(ReportingPeriod, 2) + '-01' as datetime) ReportPeriodDate
from [YourTable]
where cast(left(ReportingPeriod,4) + '-'
+ RIGHT(ReportingPeriod, 2) + '-01' as datetime)
<= cast(cast(
cast(year(getdate()) -2 as nvarchar(4))
+ '-12-31' as nvarchar(10)) as datetime)
Then you just need to delete with this logic.
delete [YourTable]
where cast(left(ReportingPeriod,4) + '-'
+ RIGHT(ReportingPeriod, 2) + '-01' as datetime)
<= cast(cast(
cast(year(getdate()) -2 as nvarchar(4))
+ '-12-31' as nvarchar(10)) as datetime)
Demo SQL Fiddle
Related
I need financial year as below format. in India financial year runs from 1 April to 31 March in every year.
1. Example 1 April 2018 to 31 march 2019 (2018 - 2019).
2. Example 1 April 2019 to 31 march 2020 (2019 - 2020).
I want below output and select query need below columns from 2018 to currently date, if the new April month starts then again new dropdown value should come, example 2020 year past then if current month April 2021 then the new dropdown value 2021 - 2022 should come like that so on.
Year FinancialYear
------------------------
2018 2018-2019
2019 2019-2020
this will gives you current & previous financial year. It uses Table Value Contructor to generate 2 rows
select datename(year, dateadd(month, -3, [date])) as [Year],
datename(year, dateadd(month, -3, [date]))
+ '-' +
datename(year, dateadd(month, +9, [date])) as [FinancialYear]
from (
values
(dateadd(year, -1, getdate())), -- previous fy
(getdate()) -- current financial year
) as fy ([date])
order by [date]
You can try using datefromparts() function as shown below. Here is the official documentation of DATEFROMPARTS (Transact-SQL).
This function returns a date value that maps to the specified year, month, and day values.
Syntax
DATEFROMPARTS ( year, month, day )
Below is the implementation for you.
create table FinancialYear (Year int)
insert into FinancialYear values (2018), (2019), (2020)
Select Year,
Cast(Year as Varchar(4)) + '-' + Cast(year + 1 as varchar(4)) as FinancialYear
,datefromparts(year, 4, 1) as [StartingDate]
,datefromparts(year + 1 , 3, 31) as [EndingDate]
from FinancialYear
Live Demo
The output is as shown in the below image.
There is an alternative by using cte you do not need table as shown below.
-- Define start and end limits
Declare #start int, #end int
Select #start = 2018, -- As you want
#end = year(getdate()) --Current Year
;With NumberSequence( Year ) as
(
Select #start as Year
union all
Select Year + 1
from NumberSequence
where Year < #end
)
--Select result
Select Year,
Cast(Year as Varchar(4)) + '-' + Cast(year + 1 as varchar(4)) as FinancialYear
,datefromparts(year, 4, 1) as [StartingDate]
,datefromparts(year + 1 , 3, 31) as [EndingDate]
from NumberSequence Option (MaxRecursion 1000)
Here is the Live Demo.
Edit
If you are using SQL Server 2005 then your query will be as shown below.
insert into FinancialYear values (2018)
insert into FinancialYear values (2019)
insert into FinancialYear values (2020)
Select Year,
Cast(Year as Varchar(4)) + '-' + Cast(year + 1 as varchar(4)) as FinancialYear
,CAST(Convert(Varchar(4), year) + '-' + '4' + '-' + '1' as DATETime) as [StartingDate]
,CAST(Convert(Varchar(4), year + 1) + '-' + '3' + '-' + '31' as DateTime) as [EndingDate]
from FinancialYear
If you want to exclude the financial year when month number is either Jan, Fab or March then you can write where condition for that as below.
Select Year,
Cast(Year as Varchar(4)) + '-' + Cast(year + 1 as varchar(4)) as FinancialYear
,CAST(Convert(Varchar(4), year) + '-' + '4' + '-' + '1' as DATETime) as [StartingDate]
,CAST(Convert(Varchar(4), year + 1) + '-' + '3' + '-' + '31' as DateTime) as [EndingDate]
from FinancialYear
where (
(ISNULL(month(getdate()), 0) >= 4 )
OR
(ISNULL(month(getdate()), 0) < 4 AND Year < year(getdate()))
)
I know its a bit lengthy, but it will work.
drop table if exists #asa
declare #getdate datetime='2025-04-06 00:00:00.000'
DECLARE #FromDate varchar(30),#ToDate varchar(30),#datediff2018 INT=CONVERT(INT,datediff(day,'2017-04-01',#getdate)/365.25)
create table #asa
(
Year varchar(10),
FY varchar(20)
)
WHILE(#datediff2018>0)
BEGIN
IF(MONTH(#getdate)>=4 AND MONTH(#getdate)<=12)
BEGIN
SET #FromDate=CONVERT(VARCHAR(10),YEAR(dateadd(year,-#datediff2018+1,#getdate)))+'-04-01'
END
ELSE IF(MONTH(#getdate)>=1 AND MONTH(#getdate)<=3)
BEGIN
SET #FromDate=CONVERT(VARCHAR(10),YEAR(dateadd(year,-#datediff2018+1,#getdate))-1)+'-04-01'
END
IF(MONTH(#getdate)>=4 AND MONTH(#getdate)<=12)
BEGIN
SET #ToDate=CONVERT(VARCHAR(10),YEAR(dateadd(year,-#datediff2018+1,#getdate))+1)+'-03-31'
END
ELSE IF(MONTH(#getdate)>=1 AND MONTH(#getdate)<=3)
BEGIN
SET #ToDate=CONVERT(VARCHAR(10),YEAR(dateadd(year,-#datediff2018+1,#getdate)))+'-03-31'
END
insert into #asa
select YEAR(#FromDate),CONVERT(VARCHAR,YEAR(#FromDate))+'-'+CONVERT(VARCHAR,YEAR(#ToDate))
set #datediff2018=#datediff2018-1
END
select * from #asa
I wrote the following query to convert 3 varchar columns into 1 datetime column:
select
MYKEY,
CAST(
CAST(YEAR AS VARCHAR(4)) +
RIGHT('0' + CAST(MONTH AS VARCHAR(2)), 2) +
RIGHT('0' + CAST(DAY AS VARCHAR(2)), 2) as DATETIME) as AD_BORN
from SOURCE
where YEAR IS NOT NULL AND MONTH IS NOT NULL AND DAY IS NOT NULL AND YEAR<>''
It works and gives me the list of expected dates.
Nevertheless, when I try to insert its results into a new table I get an error:
sql server conversion failed when converting date and/or time from
character string
This is my statement:
select
MYKEY,
CAST(
CAST(YEAR AS VARCHAR(4)) +
RIGHT('0' + CAST(MONTH AS VARCHAR(2)), 2) +
RIGHT('0' + CAST(DAY AS VARCHAR(2)), 2) as DATETIME) as AD_BORN
into MY_DATES
from SOURCE
where YEAR IS NOT NULL AND MONTH IS NOT NULL AND DAY IS NOT NULL AND YEAR<>''
MY_DATES does not exist before this query. YEAR, MONT and DAY in SOURCE are varchar (4, 2 and 2 respectively). They may contain null values.
What's wrong with that?
No need to Pad your strings. If 2012+ use try_convert()
Example
Declare #YourTable Table ([Year] varchar(50),[Month] varchar(50),[Day] varchar(50))
Insert Into #YourTable Values
(2018,1,25)
,(2018,5,55) -- Bogus Date
Select *
,AsDate = try_convert(date,[Month]+'/'+[Day]+'/'+[Year])
From #YourTable
Returns
Year Month Day AsDate
2018 1 25 2018-01-25
2018 5 55 NULL -- Bogus Date
I'm trying to write a sql query to get last week's count in the format of mm/count/yyyy. In my situation, Wednesday starts a new week. So today March 8th, 2012 is the second week of March, and the last week count is 03/01/2012. Please note, the 01 means week count not date. If consider March 1st, 2012, the last week count should be the last week of Feburary which is 02/05/2012
Update: Thanks for Steve's comment, reminding me to clear my question here. Each month starts from it's first Wednesday. So the 03/01/2012 starts from March 7th, 2012 to March 13th, 2012
Any sql query solution?
I'm using sql-server
Here's some date logic to get you started. I can't comprehend your funky "last week count" definition by the two examples, so I can't code it.
DECLARE
#Now datetime,
#Today datetime,
#MonthStart datetime,
#WeekCount int,
#Result varchar(10)
SET #Now = GetDate()
SET #Today = DateAdd(dd, DateDiff(dd, 0, #Now), 0)
SET #MonthStart = DateAdd(mm, DateDiff(mm, 0, #Today), 0)
-- relative to the actual day the month started
SET #WeekCount = ((DatePart(dd, #Today)-1) / 7) + 1
-- relative to Sunday
--SET #WeekCount = (DatePart(week, #Today) - (DatePart(week, #MonthStart) + 1
SET #Result = convert(varchar(10), #Today, 101)
SET #Result =
LEFT(#Result, 3) -- month/
+ RIGHT('z00' + convert(varchar(2), #WeekCount), 2) -- week with zero pad
+ RIGHT(#Result, 5) -- /year
SELECT
#Now as TheNow,
#Today as Today,
#MonthStart as MonthStart,
#WeekCount as WeekCount,
#Result as Result
See also SET DATEFIRST
in oracle:
select to_char( sysdate, 'w' ) from dual
#Steven,
Sorry, this didn't fit as a comment.
Your description of "[nth] week in [month]" is not clear. Your week starts on Wednesday. February first was a Wednesday, so the weeks in February, 2012, if there are indeed 5 of them, are
February 1-7
February 8-14
February 15-21
February 22-28 and
February 29 - March 6
You describe March 8 as being in the "second week of March," so the first week of March must be the previous week, which is February 29 - March 6. Note that this is also what you call "the last (fifth) week in February."
By your description, then, the weeks you write as '02/05/2012' and '03/01/2012' are the same week with different names.
What is the rule that lets you know that
You want the same "last week" when you run the program March 1 as when you run it March 8
You want that week (which is the same) described differently in these two cases.
Or does your question have a mistake in it.
Once you can describe what you need, it will be easy to program. If you don't know what you want, it will be impossible to program.
In SQL Server these queries return 1,1,2,5
select ((DATEPART(dd, 'March 01, 2012')-1)/7) + 1
select ((DATEPART(dd, 'March 07, 2012')-1)/7) + 1
select ((DATEPART(dd, 'March 08, 2012')-1)/7) + 1
select ((DATEPART(dd, 'March 31, 2012')-1)/7) + 1
So this may be what you need
declare #dt datetime = 'March 31, 2012'
select
CONVERT(nvarchar(4), DATEPART(month,#dt)) + '/' +
CONVERT(nvarchar(4), ((DATEPART(dd, #dt)-1)/7) + 1) + '/' +
CONVERT(nvarchar(4), DATEPART(year,#dt))
which produces '3/5/2012'
SELECT
RIGHT(100 + MONTH(D) , 2) + '/' +
RIGHT(100 + (DAY(D) + 6) / 7, 2) + '/' +
DATENAME(YEAR, D)
FROM (
SELECT DATEADD(WEEK, -1, GETDATE()) AS D
) s
I think that should do it, I don't get the value for last week because it was confusing and the answer is cleaner that way, you can just add a DATEADD(day,-7,date) somewhere.
SET DATEFORMAT YDM
CREATE TABLE #Dates (Date DATETIME)
INSERT INTO #Dates VALUES ('2012-31-03');
INSERT INTO #Dates VALUES ('2012-15-02');
INSERT INTO #Dates VALUES ('2012-02-04');
INSERT INTO #Dates VALUES ('2012-02-05');
WITH Mondays as (
SELECT DATEADD(week, DATEDIFF(week,0, DATEADD(day,6-DATEPART(day,d.Date),d.Date) ), 0) FirstMonday,
DATEADD(week, DATEDIFF(week,0, DATEADD(day,6-DATEPART(day,DATEADD(month, -1, d.Date)),DATEADD(month, -1, d.Date)) ), 0) FirstMondayOfLastMonth,
d.Date
FROM #Dates d),
Wednesday as (
SELECT CASE WHEN DATEPART(day,m.FirstMonday) <= 5
THEN DATEADD(day,2,m.FirstMonday)
ELSE DATEADD(day,-5,m.FirstMonday) END FirstWednesday,
CASE WHEN DATEPART(day,m.FirstMondayOfLastMonth) <= 5
THEN DATEADD(day,2,m.FirstMondayOfLastMonth)
ELSE DATEADD(day,-5,m.FirstMondayOfLastMonth) END FirstWednesdayOfLastMonth,
m.Date
FROM Mondays m)
SELECT w.Date,
CASE WHEN w.Date >= w.FirstWednesday THEN
RIGHT('0' + CAST(DATEPART(month,w.Date) AS NVARCHAR(2)),2)
+ '/0' + CAST(DATEDIFF(week,w.FirstWednesday, w.Date) + 1 AS NVARCHAR(2))
+ '/' + CAST(DATEPART(year,w.Date) AS NVARCHAR(4))
ELSE
RIGHT('0' + CAST(DATEPART(month,w.FirstWednesdayOfLastMonth) AS NVARCHAR(2)),2)
+ '/0' + CAST(DATEDIFF(week,w.FirstWednesdayOfLastMonth, w.Date) + 1 AS NVARCHAR(2))
+ '/' + CAST(DATEPART(year,w.FirstWednesdayOfLastMonth) AS NVARCHAR(4))
END AS weekDate
FROM Wednesday w
DROP TABLE #Dates
The result is :
Date weekDate
2012-03-31 00:00:00.000 03/04/2012
2012-02-15 00:00:00.000 02/03/2012
2012-04-02 00:00:00.000 03/05/2012
2012-05-02 00:00:00.000 05/01/2012
I would like select data between two date, without day
An input example:
start month: 9 , start year: 2011
end month: 3, end year: 2012
I think that there are two way to do this.
The first is convert start month and start year to date like 2011-09-01 and convert last date to 2012-03-31, but this requires calculation of the last day of end month. Obtained these date we can use a BEETWEN function for the WHERE clause (but, is the CONVERT function reliable?)
The second solution is to use the DATEPART function like in the following code:
I try to explain: if end year is equal to the initial year, then month must be between the start and end months; else if the final months is greater than the initial years if different from the initial and final year, I take everything in between; else if the final year, the month must be less than or equal to the final month, if the initial year, month must be greater than or equal to the final month
Can you help me do this in the best way? Is correct, the solution I adopted?
declare #IndDebitoCredito bit,#ProgTributo int,#mi as integer,#ai as integer,#mf as integer,#af as integer,#IDAnagrafica varchar(5)
select #mi = 01,#ai = 2011,#mf = 12,#af = 2011,#IDAnagrafica = 'DELEL',#IndDebitoCredito = 1
select distinct rrd.IDTributo
from TBWH_Delega d
--inner join TBWH_SezioneDelega sd on d.IDDelega = sd.IDDelega
inner join TBWH_Rigo rd on rd.IDDelega = d.IDDelega
inner join TBWH_RataRigo rrd on rrd.IDRigo = rd.IDRigo
where
(
DATEPART(MM,d.DataDelega)<=#mf and
DATEPART(MM,d.DataDelega)>=#mi and
DATEPART(YYYY,d.DataDelega)=#ai and
#af = #ai
)
OR
(
--anno finale magg. anno iniziale
#af > #ai AND
(
( -- delega nell'intervallo
DATEPART(YYYY,d.DataDelega)<#af AND
DATEPART(YYYY,d.DataDelega)>#ai
-- DATEPART(MM,d.DataDelega)>=#mi
)
OR
( -- delega limite destro
DATEPART(YYYY,d.DataDelega)=#af AND
DATEPART(MM,d.DataDelega)<=#mf
)
OR
( -- delega limite sinistro
DATEPART(YYYY,d.DataDelega)=#ai AND
DATEPART(MM,d.DataDelega)>=#mi
)
)
)
GO
Your first solution is almost there, but is more complicated than it needs to be and won't work anyway. It will miss out any rows from the last day of the end month.
You can add one month to the end month and then use BETWEEN on the first of each month. eg.
start month: 9 , start year: 2011
end month: 3, end year: 2012
BETWEEN '2011-09-01' AND '2012-04-01'
or, as JNK points out, this will be better:
DataDelega >= '2011-09-01' AND DataDelega < '2012-04-01'
You'll need to add in some logic to deal with the end month being December, but this looks like the simplest way of doing it.
You are WAY overcomplicating this. You really only need two comparisons:
Is the month and year after or equal to the initial value?
Is the month and year before or equal to the final value?
Try:
SELECT *
FROM MyTable
WHERE Datefield BETWEEN
CAST(#mi as varchar) + '/1/' + CAST(#ai as varchar)
-- first of first month
AND
DATEADD(DAY, -1, (DATEADD(Month, + 1, (CAST(#mf as varchar) + '/1/' + CAST(#af as varchar)))))
-- Last day or final month
SELECT *
FROM Table
WHERE DateField
BETWEEN CONVERT(DATE, CONVERT(CHAR(4), #ai) + RIGHT('00' + CONVERT(VARCHAR(2), #mi), 2) + '01', 112)
AND DATEADD(DD, -1, DATEADD(MM, 1, CONVERT(DATE, CONVERT(CHAR(4), #af) + RIGHT('00' + CONVERT(VARCHAR(2), #mf), 2) + '01', 112)))
Avoid using expressions on the DateField columns, as it makes query not SARGable.
I would use:
WHERE DateToCheck >= --- first day of StartMonth
DATEADD( mm, #StartMonth-1,
DATEADD( yy, #StartYear-2000, '2000-01-01')
)
AND DateToCheck < --- first day of next month (after EndMonth)
DATEADD( mm, #EndMonth,
DATEADD( yy, #EndYear-2000, '2000-01-01')
)
DECLARE #mi INT
, #ai INT
, #mf INT
, #af INT
SELECT #mi = 01
, #ai = 2011
, #mf = 12
, #af = 2011
--local variables to hold dates
DECLARE #i DATETIME
, #f DATETIME
--build strings to represent dates in YYYYMMDD format
--add a month to the #f date
SELECT #i = CONVERT(VARCHAR(4), #ai) + RIGHT('0' + CONVERT(VARCHAR(2), #mi),
2) + '01'
, #f = DATEADD(month, 1,
CONVERT(VARCHAR(4), #af) + RIGHT('0'
+ CONVERT(VARCHAR(2), #mf),
2) + '01')
--select data where date >= #i, and < #f
SELECT *
FROM MyTable
WHERE DateField >= #i
AND DateField < #f
I want to know how can I get the year and month into my database. For example, suppose it’s August, 2011. The output that I need is like this: CAB 11 08 001 (CAB + YEAR + MONTH + CURRENT NO. in tracking number. )
This is my SQL:
ALTER PROCEDURE [dbo].[generateTrackNo] AS
Declare #tempYear VARCHAR(5),#tempMonth VARCHAR(5)
Set #tempYear = Year(GetDate())
Set #tempMonth = Month(GetDate())
SELECT 'CAB' + Right(Cast(Year(GetDate()) as varchar(10)),2)+ Right(Cast(Month(GetDate()) as varchar(10)),2) + Right('000000'+ Cast(CurrentNo as varchar(10)), 5) from tblTrackNo where GenYear = #tempYear
--UPDATE tblTrackNo SET CurrentNo = CurrentNo + 1 where GenYear = #tempYear
The output for this is CAB1180035, but I need CAB1108035. I need to put zero(0) 08 like this for the month.
In my table I have only genYear and Current No. Do I need to add another column for MONTH?
It looks like you're making separate columns for YEAR, MONTH, etc.
Most (all?) DBMSs I'm aware of have a Date type. Use it. They put a lot of useful stuff in it, like accepting date inputs in different formats and giving them as output in pretty much any format you can think of.
For example, if you have a DT column of type Date in Oracle, you can output month as
SELECT TO_CHAR(DT, "MM") FROM MYTABLE;
and the month will always be displayed as 2 digits (01, 02, ... 12)
SELECT
'CAB'
+ RIGHT(YEAR(GetDate()),2)
+ RIGHT('0' + CONVERT(VARCHAR, MONTH(GetDate())),2)
+ Right('00000' + Cast(CurrentNo as varchar(10)), 5)
That might work..
Using your method \ logic..
Right('0' + Cast(Month(GetDate()) as varchar(10)),2)