I have a table that has columns reportyear and reportmonth. For reportyear, the column is a vharchar (4) that equals to year 2016 format. For reportmonth, it is a varchar (2) that has a 01, 02, 03, etc. format. I have a data parameter that concatenates the two since our end users want a drop down date. So my parameter is #ReportDate varchar (7).
My problem is for one of my selects in my stored procedure, I need to put a where clause where it goes back a month. So if my parameter equals to '2016-11', I want a where clause where it returns '2016-10'. I have successfully done this using the flowing query:
SUBSTRING(#Reportdate, 1, 4) + '-' + cast(substring(#ReportDate, 6, 7) -1 as varchar(20))
This returns '2016-10' if I pick '2016-11' as any report date parameter.
But upon further thinking, this would not work if my report date is in January because the above query just literally subtract a string value. So if I pick '2016-01', the above query would return '2016-0'.
For Example:
Declare #Reportdate varchar(7) = '2016-01'
Select AsDate = dateadd(MM,-1,#ReportDate+'-01')
,AsSting = left(convert(date,dateadd(MM,-1,#ReportDate+'-01'),101),7)
Returns
AsDate AsSting
2015-12-01 2015-12
You can just use case:
select concat(#ReportYear - 1,
(case when #ReportMonth = '01' then '12'
else right(concat('0', #ReportMonth - 1))
end)
)
SQL Server will treat the strings as ints -- with no conversion errors for your values. concat() then converts them back into strings.
EDIT:
I see, this is backwards. Let's add one to the columns in the table and compare to #Report_Month:
where (reportmonth = 12 and
right(#ReportDate, 2) = '01' and left(#Report_date, 4) = reportyear + 1
) or
(left(#ReportDate, 4) = reportyear and
right(#ReportDate, 2) = reportmonth + 1
)
But after considering this, I think you should use a computed column:
alter table t add reportdate as ( datefromparts(reportyear, reportmonth, 1) );
Then simply do:
where dateadd(month, 1, reportdate) = cast(#reportdate + '01' as date)
Of course, you can do the explicit comparison:
where (dateadd(month, 1, datefromparts(reportyear, reportmonth, 1)) =
cast(#reportdate + '01' as date)
)
Note that both of these assume that #reportdate is a string.
Related
I have 1 column that displays year number in the format 1999 and I have another column that displays month number as 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12.
How do I get the single months to display with a 0 in front? I need to combine these 2 columns to display in the form of yyyy/mm so it will be 1999/01 for January 1999.
I tried:
SELECT
YearNumber + '/' + FORMAT(MonthNumber, 'mm') AS PaymentMonth
But I get this error:
Conversion failed when converting the varchar value '/' to data type smallint
Please try:
SELECT
CAST(YearNumber AS varchar(4)) + '/' +
LEFT('0' + CAST(MonthNumber AS varchar(2)), 2) AS PaymentMonth;
Another option, using case when:
The table:
select * from mytable
# YearNumber MonthNumber
# 1999 2
# 2000 11
select YearNumber || '/' ||
(case when MonthNumber < 10 then '0' else '' end) ||
MonthNumber as YearMonth
from mytable
# YearMonth
# 1999/02
# 2000/11
Note: the above works in sqlite, which tends to be more permissive with column types. In SQL Server, if the columns are not strings already then you may need to cast(YearNumber as char(4)) or perhaps use the concat function:
select
concat(YearNumber, '/',
(case when MonthNumber < 10 then '0' else '' end),
MonthNumber) as YearMonth
from mytable
Other DBMSes have different dialects, they may differ slightly.
SQL Date Format with the FORMAT function
Use the FORMAT function to format the date and time data types from a date column (date, datetime, datetime2, smalldatetime, datetimeoffset, etc. data type) in a table or a variable such as GETDATE()
To get DD/MM/YYYY use SELECT FORMAT (getdate(), 'dd/MM/yyyy ') as date
To get MM-DD-YY use SELECT FORMAT (getdate(), 'MM-dd-yy') as date.
You can use the concat() function to join them. Depending on the database you can use || instead.
select concat(col1, '/', col2) from tbl;
This is also standard, but not enabled by default on MySQL, and possibly other databases.
select col1 || '/' || col2 from tbl;
Receive date as "19-May" and need to convert it as '05/01/2019', "19-June" to '06/01/2019'.
I have tried various date conversion but it didn't work.
You can try this. Storing date in this format is not a good/suggestion you should use the proper data type which are meant and available for.
You should update the values with proper date time value and then change the data type also. It will save your time & you do not need these conversions every time.
Select Try_Cast('19-May 2019' as Datetime)
OR
Select Try_Cast('19-May' + '2019' as Datetime)
To get the first date of month you can try the below query.
SELECT DATEADD(month, DATEDIFF(month, 0, Try_Cast('19-May 2019' as Datetime)), 0) AS StartOfMonth
Edit
To get the first date of month as per the given data in string, you can use the below query.
declare #dateinStr varchar(20) = '19-May'
Select try_cast('01-' + Replace(#dateinStr, LEFT(#dateinStr, 3), '') + LEFT(#dateinStr, 2) as Datetime) as Date
Here is the demo.
I suppose the months will be 3 chars only, if so then
Select s,
try_Cast(concat(right(s, 3), ' 2019') as Datetime)
from
(
values
('19-May'),
('19-Jun')
) t(s);
If the months is really comes like "June" & "August" then
select s,
try_cast(concat(substring(s, charindex('-',s)+1, 3), ' 2019') as date)
from
(
values
('19-May'),
('19-June'),
('15-August')
) t(s);
If you need to format it as mm/dd/yyyy then use 101 style.
You can do :
SELECT DATEADD(DAY, 1, EOMONTH(CONVERT(DATE, Dates + '-2019'), -1))
FROM ( VALUES ('19-May'), ('19-June')
) t(Dates);
StartDate = 01/01/2013
EndDate = 12/31/2019
I need to get the year column like '2013-14' , '2014-15' , 2015-16 and so on.
For example, the 2013-14 year should contains date details from Jun 2013 to May 2014. Like wise i need to get the year upto End date. Please help me out.
concat(datepart(YY,StartDate ),'-', RIGHT(YEAR(StartDate ),2) + 1)
I used the above format. i can get the output as 2013-14. But i need to specify the range of month for splitting years.
Regards,
Vanmathi
Use the FORMAT function:
SELECT
FORMAT(StartDate, 'yyyy-MM'),
FORMAT(EndDate, 'yyyy-MM')
Read all about the FORMAT function on the official MSDN documentation page.
Use a user defined function to slice up the date and then text concatenation.
CREATE FUNCTION GetSlicedYear(#TheDate date)
RETURNS varchar(7)
AS
BEGIN
DECLARE #SlicedYear varchar(7)
IF DATEPART(month, #TheDate) < 6
SELECT #SlicedYear = (DATEPART(year, #TheDate) -1 ) +"-"+ RIGHT(CAST(YEAR(#TheDate) As varchar(4)),2)
ELSE
SELECT #SlicedYear = DATEPART(year, #TheDate) +"-"+ RIGHT(CAST((YEAR(#TheDate) +1) As varchar(4)),2)
RETURN #SlicedYear
END
Then something like this to Order (or group).
SELECT SomeField, GetSlicedYear(SomeDate) FROM SomeTable ORDER BY GetSlicedYear(SomeDate)
You can use the below select statement -
select FORMAT(StartDate , 'yyyy') + '-' + FORMAT(EndDate , 'yyyy')
I am trying to change the date format of a column, the column is set as varchar column name date time. The problem is that i cannot actually change the data type because the data is automatically inputted by a PLC on the automation side. I need the date in a date or numeric value because when i run my queries i need to give the system a date range. I am trying to use substrings to work around this issue but am getting an error saying that the data type is out of range. here is the syntax of my query.
select cast(
(substring(datetime, 1, 4) + '-' +
SUBSTRING(DateTime, 5, 2) + '-' +
SUBSTRING(DateTime, 7, 2) + ' ' + '00:00:00.000') as dateTime) as "Date"
, ID1
, ID2
, diameter
, WeightTheoretical
, WeightActual
, StockType
from table1
where datetime is not null
and datetime <> ''
and datetime <> '0'
order by "Date", ID1;
Edit- the date format is as such 20120622:00:00:00:000
Assuming your date is with the format yyyymmdd, you can convert the varchar to datetime like this:
select convert(datetime, columname, 112)
It looks from your SQL that your date string is of the format YYYYMMDD
This should convert fine using either the CAST or CONVERT functions:
eg
SELECT CONVERT(datetime,'20120601')
SELECT CAST('20120601' as datetime)
both return the expected value as a datetime.
EDIT: Based on the supplied format you specified, I'd use the SubString to chop the supplied data down a bit:
eg
SELECT CONVERT(datetime,SUBSTRING('20120601',1,8))
Based on the format of your data in the table (20120622:00:00:00:000) you can do the following:
declare #date varchar(50)
set #date = '20120622:00:00:00:000'
select cast(left(#date, 8) as datetime)
or
select convert(datetime, left(#date, 8))
results:
2012-06-22 00:00:00.000
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