I have calculated a date average from several dates and I'm trying to get the result of the average date, but I'm getting the following error:
Conversion failed when converting date and/or time from character string.
Here's the SQL query I tried:
select
CONVERT(DATE, LEFT(convert(varchar(10), AVG(convert(int, convert(varchar(10), OnMarkDate, 112)))), 8))
from
#tbl_XMLResult
Here are the date values in table #tbl_XMLResult:
'2001-10-11',
'2001-10-03',
'2001-09-24',
'2000-05-31',
'2001-10-15',
'2008-01-01'
These dates are of type date.
Are you looking for something like this?
I calculate the differences in days from the oldest date (2000-05-31) in the first CTE, then I calculate the average of those day differences (all int values), and then I add this average to the oldest date, to get an "average" date.
DECLARE #input TABLE (OnMarkDate DATE)
INSERT INTO #input (OnMarkDate)
VALUES ('2001-10-11'), ('2001-10-03'), ('2001-09-24'),
('2000-05-31'), ('2001-10-15'), ('2008-01-01');
DECLARE #OldestDate DATE = '2000-05-31';
;WITH DateAndDayDiff AS
(
SELECT DayDiff = DATEDIFF(DAY, #OldestDate, OnMarkDate)
FROM #INPUT
), AverageDayDiff AS
(
SELECT AverageDiff = AVG(DayDiff)
FROM DateAndDayDiff
)
SELECT
DATEADD(DAY, AverageDayDiff.AverageDiff, #OldestDate)
FROM AverageDayDiff
When I do this, I get 2002-07-30 as the "average" date for this list of dates.
Related
I have a table containing 3 columns [MONTHNAME], [MONTHSTART] and [MONTHEND]. For reporting, I need to group all prior months together but leave the current month grouped by weeks. To do this I need to get the prior month's ending date. Below is the query I am using and it works properly, but is there a better way of determining the prior month's ending date without creating a table or using CTE with the LAG function? There was no way I found to get the LAG function to return a single value so I had to use the following. Our month ending dates do not fall on the calendar month ending date so I am pulling the data from a custom calendar.
DECLARE #tblMonthEndingDates TABLE
([MONTHSTART] DATE
,[MONTHEND] DATE
)
INSERT INTO #tblMonthEndingDates
VALUES('01-01-2018', '01-26-2018'),
('01-27-2018', '03-02-2018'),
('03-03-2018', '03-30-2018'),
('03-31-2018', '04-27-2018'),
('04-28-2018', '06-01-2018'),
('06-02-2018', '06-30-2018'),
('07-01-2018', '07-27-2018'),
('07-28-2018', '08-31-2018'),
('09-01-2018', '09-28-2018'),
('09-29-2018', '10-26-2018'),
('10-27-2018', '11-30-2018'),
('12-01-2018', '12-31-2018')
DECLARE #dtTbl TABLE(RN INT
,MS DATE
,ME DATE
);
INSERT INTO #dtTbl
SELECT ROW_NUMBER() OVER(ORDER BY [MONTHSTART]) AS ROWNUM
,[MONTHSTART]
,[MONTHEND]
FROM #tblMonthEndingDates;
WITH cteDt
AS
(
SELECT d2.[MS]
,LAG(d1.[ME]) OVER(ORDER BY d1.[MS]) AS PRIORDT
,d2.[ME]
FROM #dtTbl d1
LEFT JOIN #dtTbl d2 ON d1.[RN] = d2.[RN]
)
SELECT [PRIORDT]
FROM cteDt
WHERE [MS] <= GETDATE() AND [ME] >= GETDATE()
So for this month I would want 09-28-2018 as the return value which the query does, I just want to know if there is a better/shorter way of returning that value.
You can do something like this:
Select
Max(MonthEnd)
From #tblMonthEndingDates
Where MonthEnd <= GetDate()
That will give you the most recent MonthEnd date before or on today's date. Obviously, if you need strictly before, you'd use < rather than <=
I used this query to get the start and end dates for the last #n months. You can adapt to meet your needs.
declare #t table (SD date,ED date)
declare #i int = 0
,#SD date
,#ED date
,#datetoEval date
,#EOM date
,#n int = 60
while(#i<=#n)
BEGIN
set #datetoEval = DATEADD(month,-1*#i,getdate())
set #SD = cast(cast(month(#datetoEval) as varchar(2)) + '/1/' + cast(year(#datetoEval) as varchar(4)) as DATE)
set #ED = dateadd(day,-1,DATEADD(MONTH,1,#SD))
insert into #t
values(#SD,#ED)
set #i=#i+1
END
select * from #t
I was overthinking it. Last month ended the day before this one started.
SELECT DATEADD(DAY, -1, MONTHSTART) AS MONTHEND
FROM #tblMonthEndingDates
WHERE
GETDATE() BETWEEN MONTHSTART AND MONTHEND
I have a date time column in sql DB - named check_time. I want to write a select query where this check_time should be equals to today's date (no need to consider what time is. Only need to check current date).
For example check_time in table is inserted as 03/08/2017 12:00:00.000 AM.
I have written like below
SELECT * FROM time_details
WHERE check_time = DATEADD(day, DATEDIFF(day,0,GETDATE()),0)
But it returns nothing.
This is the correct syntax:
SELECT * FROM time_details where (DATEDIFF(d, check_time, GETDATE()) = 0)
Just CAST the today's date to DATE.
Query
select * from time_details
where check_time = cast(getdate() as date);
Try with
SELECT * FROM time_details where DATE(check_time) =CURDATE()
The DATE function is going to extract just the date from you datetime field while the CURDATE is returning the current date.
Check with the sql query
SELECT * FROM time_details where DATE(check_time)=DATE(NOW())
this should work
SELECT * FROM time_details where check_time =convert(varchar, getdate(), 101)
SELECT CONVERT(datetime,'17/05/2015 22:15:00',103)
output:
2015-05-17 22:15:00.000
I want include 2 column is Date+Time
Example: Colunm Date and Time
**Date** **Time**
17/05/2015 22:15:00
but Error Query
SELECT CONVERT(datetime,[Date]+' '+[Time],103) FROM LPTables
Conversion failed when converting date and/or time from character string.
Just add the time portion to the date portion:
SELECT DATEADD(ms, DATEDIFF(ms, '00:00:00', [Time]), CONVERT(DATETIME, [Date]))
FROM LPTables
This will give you accuracy to the millisecond.
Just enclose your columns with ().
SELECT CONVERT(datetime,([Date]+' '+[Time]),103) FROM LPTables
WHERE ISNULL([Date],'')!='' AND ISNULL([Time],'')!=''
Sample :
EDIT -----------------
I'm going to try to clarify.
I have this table:
A user will input a start date and an end date.
Let's say the user inputs 2011-10-21 for the start and 2011-12-18 for the end.
This will bring back all the records:
But what if the user inputs 2011-10-22 and 2011-12-18?
The 2011-10-22 is BETWEEN the date range of the FIRST ROW 2011-10-21 (start) & 2011-10-23 (end).
SINCE IT IS BETWEEN THE DATE RANGE OF THE FIRST RECORD, I WANT to return that row as well. I DO NOT WANT TO EXCLUDE IT.
So if if I run a query like this:
select * from table where PayPeriodStart between '2011-10-22' and '2011-12-18'
I WANT to see this:
and NOT this:
PLEASE NOTE... the user can enter in any start or end date and it'll be at least 1 week.
So they can pick 2011-11-09 (start) and 2011-12-04 (end) for example.
You'll want the search criteria to return the rows where the period start date is before the end date criteria and the period end date is after the start date criteria. In other words:
declare #Table table (PayPeriodStart smalldatetime, PayPeriodEnd smalldatetime)
insert into #Table (PayPeriodStart, PayPeriodEnd)
select '2010-01-01', '2010-12-31' -- test before the criteria; is not returned
union select '2011-10-21', '2011-10-23' -- overlaps start date; is returned
union select '2011-10-24', '2011-11-06' -- fully in date range; is returned
union select '2011-11-07', '2011-11-20' -- fully in date range; is returned
union select '2011-11-21', '2011-12-04' -- fully in date range; is returned
union select '2011-12-05', '2011-12-18' -- overlaps end date; is returned
union select '2012-01-01', '2012-12-31' -- test after the criteria; is not returned
-- This yields all but the first row
select * from #Table where PayPeriodStart between '2011-10-22' AND '2011-12-10'
-- This will yield all the rows that overlap the search criteria
select * from #Table
where PayPeriodStart <= '2011-12-10' -- the end search date
and PayPeriodEnd >= '2011-10-22' -- the start search date
If you are looking for all records that are valid between '2011-10-22' AND '2011-12-10' , this is the query you should use
select * from table where ('2011-10-22' >= PayPeriodStart AND '2011-10-22' <= PayPeriodEnd) Or ('2011-10-22' < PayPeriodStart AND '2011-12-10' > PayPeriodEnd)
I have never been a fan of the between syntax for the edge case reason, so I tend to use this syntax instead:
select * from table where ('2011-10-22' <= PayPeriodStart AND PayPeriodStart <= '2011-12-10')
Same end result, but I can ensure I include the boundaries as needed.
Are you asking for
select * from table where '2011-10-22' between PayPeriodStart AND PayPeriodEnd
AND '2011-12-10' between PayPeriodStart AND PayPeriodEnd
If you want to get data based on first of the month and last of the month or for fixed time interval like 30 day window, you may have to use DateAdd, DateDiff functions to calculate dates.
Following example is based on FirstOfTheMonth, LastOfTheMonth calculation
your reference data
declare #refDate date = getdate()
select #min = dateadd(mm, datediff(mm, 0, #refDate), 0) -- First of the month
, #max = dateadd(dd, -1, dateadd(mm, datediff(mm, 0, #refDate) + 1, 0)) --Last of the month
I have database with a Publications table that is many-to-may joined to iself through a SubPublications table
My stored procedure returns all of the distinct Year-Month combos from a ReleaseDate field of Publications of a specified type that are not related to a specific (by id) publication (hence the 2 params, see below).
QUESTION:
The proc works fine, but I want the return column type as DateTime2 with a dummy date of 1. As it is now, it returns 2 columns of integers. How do I do this?
I know I could do the conversion in my app code, but I'd rather have it delivered as a datetime from the DB.
My SQL ain't great. I don't even know if I should use a cast or a convert.
I can't find an example online of converting back to datetime within a query like that. Can anyone help? Here's the proc I wrote, as it stands:
ALTER PROCEDURE sp_DistinctPubMonthYears
#PubType char(1),
#PubId int = 0
AS
BEGIN
SELECT
DISTINCT TOP (100) PERCENT
DATEPART(month, ReleaseDate) AS month,
DATEPART(year, ReleaseDate) AS year
FROM(
SELECT
Publications.ReleaseDate AS ReleaseDate,
Publications.PublicationId As PubId,
Publications.PubType AS PubType,
SubPublications.PublicationId AS ParentId
FROM
Publications LEFT JOIN SubPublications
ON
Publications.PublicationId = SubPublications.PublicationId
WHERE
Publications.PubType = #PubType AND
Publications.PublicationId <> #PubId AND
(
SubPublications.PublicationId <> #PubId OR
/*either it's parent is NOT the one we're searching on or */
SubPublications.PublicationId IS NULL
/*or it's not joined to anything at all */
)
) AS sub
ORDER BY year ASC, month ASC
END
GO
You don't need TOP and you may as well ORDER BY the expression.
This DATEADD/DATEDIFF expression will give you start of current month
SELECT DISTINCT
CAST(
DATEADD(month, DATEDIFF(month, 0, ReleaseDate), 0) AS datetime2
) AS myCol
FROM(
...
ORDER BY
DATEADD(month, DATEDIFF(month, 0, ReleaseDate), 0)
Edit: As Faust mentioned, we can order on the alias if you prefer.
...
ORDER BY
myCol
In this case the result is the same.
If the CAST was to varchar then you would have different results. This is why I tend to use the expression not the alias but it's quite trivial. Surely I'd test my changes..., no?
DATEADD(MONTH, DATEDIFF(MONTH, '1600-01-01T00:00:00', ReleaseDate), '1600-01-01T00:00:00') should get you your yyyy-MM-dd 00:00:00 date. 1600-01-01T00:00:00 is just an arbitrary date that is best picked to be prior to any dates you may be storing in your ReleaseDate column.