SQL Server update caused Datediff to not work - sql-server

I know there were several articles about this topic already and I went through them but I still am not able to get this to run properly. I also used DATEDIFF_BIG, but then I get this error:
DATEDIFF_BIG is not a recognized built-in function name.
This used to be able to run but I think there was a SQL server update and now all of the TAT queries are breaking.
SELECT
MSTR.FIRST_OF_MTH AS [MONTH],
COALESCE(R.[AREA],T.[AREA]) AS [AREA],
COALESCE(R.NUM_REQUESTS,0) AS NUM_REQUESTS,
COALESCE(R.DURATION_REQ,0) AS DURATION_REQ,
COALESCE(T.NUM_TRANS,0) AS NUM_TRANS,
COALESCE(T.DURATION_TRANS,0) AS DURATION_TRANS
FROM
(
SELECT FIRST_OF_MTH
FROM [EPICDW].[DBO].[DATE_EXT]
WHERE (YEAR([DATE_EXT].[THEDATE]) BETWEEN YEAR(GETDATE()) - 1 AND YEAR(GETDATE()))
GROUP BY FIRST_OF_MTH
) MSTR
LEFT JOIN
(
--transactions
SELECT
DATEADD(month, DATEDIFF(month, 0, [CLOSE_DT]), 0) AS [MONTH],
[TEAM] AS AREA,
SUM(1) AS NUM_TRANS,
SUM(B.[Calendar_Duration]) AS DURATION_TRANS
FROM [dbo].[v_tab_config_bl_trans_comb]
CROSS APPLY fn_Ben_Ops_Turnaround ([OPEN_DT], [CLOSE_DT]) B
WHERE Year([CLOSE_DT]) BETWEEN YEAR(GETDATE()) - 1 AND YEAR(GETDATE())
GROUP BY
DATEADD(month, DATEDIFF(month, 0, [CLOSE_DT]), 0),
[TEAM]
) T
ON MSTR.FIRST_OF_MTH = T.[MONTH]
LEFT JOIN
(
--requests
SELECT
DATEADD(month, DATEDIFF(month, 0, [CLOSED_DT]), 0) AS [MONTH],
TEAM AS AREA,
SUM(1) AS NUM_REQUESTS,
SUM([DUR_CAL]) AS DURATION_REQ
FROM [dbo].[v_tab_config_requests]
WHERE year([CLOSED_DT]) BETWEEN YEAR(GETDATE()) - 1 AND YEAR(GETDATE())
GROUP BY DATEADD(month, DATEDIFF(month, 0, [CLOSED_DT]), 0), TEAM
) R
ON MSTR.FIRST_OF_MTH = R.[MONTH]
AND T.AREA = R.AREA

Related

Count Like Description column and sum based on equipment

In SQL Server, I am trying to group equipment and then count the 'like' Descriptions to get the occurrences. Has anyone done anything like that?
Select
Equip, Count like Description,
from
WorkOrder (nolock)
where
DateTm Between DATEADD(month, DATEDIFF(month, 0, getDate()), 0) and DATEADD(month, DATEDIFF(month, -1, getDate()), -1)
Group by
Equip, Description
order by
Equip Asc
This should work. If you want to search with list of descriptions, then add the where class with description like.
Select Equip,Description, count(*) as Count,
from WorkOrder (nolock)
where DateTm Between DATEADD(month, DATEDIFF(month, 0, getDate()), 0) and
DATEADD(month, DATEDIFF(month, -1, getDate()), -1)
Group by Equip,Description order by Equip Asc
I think what you are trying to do is to get those with same description per Equip. You can group by and having clause for this requirement.
select description
, Equip
, count(Equip)
from WorkOrder (nolock)
where DateTm Between dateadd(month, DATEDIFF(month, 0, getDate()), 0)
and dateadd(month, DATEDIFF(month, -1, getDate()), -1)
group by description, Equip
having count(description) > 1
WITH cte
AS (SELECT equip,
description,
CASE
WHEN description LIKE '%part was struck%'
OR description LIKE '%Struck part%' THEN 'STRUCK PART'
WHEN description LIKE '%FAILURE%' THEN 'FAILURE'
ELSE 'RANDOM'
END AS DESCRIPTION_GROUP
FROM workorder (nolock)
WHERE datetm BETWEEN Dateadd(month, Datediff(month, 0, Getdate()), 0)
AND
Dateadd(month, Datediff(month, -1,
Getdate()),
-1
))
SELECT equip,
description_group,
Count(*)
FROM cte
GROUP BY equip,
description_group
ORDER BY equip ASC

Divide results of two queries and obtain result in third query

I have two SQL queries that I want to divide. On their own each query works, and I want to divide their results and obtain into third variable, but I am unsure how.
This query calculate no of cancelled members
(select count(*) as No_of_Member_Cancelled, M.HomeBranch,M.LocationName from
AX.Memberships M
where M.ActiveEnd between DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()) - 1,
0) and DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()) ,-1)
group by M.HomeBranch,M.LocationName) as g1
This query calculate the no of live members
(select count(*)as No_of_Live_Member , M.HomeBranch,M.LocationName
from AX.Memberships M
where M.ActiveStart between DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()) -
1, 0) and DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()) ,-1)
group by M.HomeBranch,M.LocationName) as g2
We obtain results like this
if x = g1/g2
x , LocationName , HomeBranch in one table
Best to change those to temp tables then you can do it like this:
select No_of_Member_Cancelled / No_of_Live_Member as x, HomeBranch, LocationName
from G1
join G2 on g1.HomeBranch = g2.HomeBranch and g1.LocationName = g2.LocationName
group by HomeBranch, LocationName
Try this...
SELECT CAST (g1.no_of_member_cancelled AS DECIMAL(10, 2)) /
CAST (g2.no_of_live_member AS DECIMAL(10, 2)) AS x,
g1.homebranch,
g1.locationname
FROM (SELECT Count(*) AS No_of_Member_Cancelled,
M.homebranch,
M.locationname
FROM ax.memberships M
WHERE M.activeend BETWEEN Dateadd(month, Datediff(month, 0, Getdate())
- 1, 0)
AND
Dateadd(month, Datediff(month, 0,
Getdate())
, -1)
GROUP BY M.homebranch,
M.locationname) AS g1
INNER JOIN (SELECT Count(*)AS No_of_Live_Member,
M.homebranch,
M.locationname
FROM ax.memberships M
WHERE M.activestart BETWEEN Dateadd(month, Datediff(month, 0
,
Getdate()) - 1,
0) AND
Dateadd(month, Datediff(month,
0, Getdate(
)), -1)
GROUP BY M.homebranch,
M.locationname) AS g2
ON g1.homebranch = g2.homebranch
AND g1.locationname = g2.locationname
You will need to cast (or convert) your number of cancelled and live members to the datatype that fits your situation given the size of your potential values. You probably should take precaution so you don't get a division by zero error.
SELECT distinct CAST (g1.no_of_member_cancelled AS DECIMAL(10, 2)) /
CAST (g2.no_of_live_member AS DECIMAL(10, 2)) AS x,
g1.homebranch,
g1.locationname,
g1.month,
g1.year
FROM (SELECT Count(*) AS No_of_Member_Cancelled,
M.homebranch,
M.locationname,
month(M.ActiveStart) month,
YEAR(M.ActiveStart) year
FROM ax.memberships M
WHERE M.activeend BETWEEN Dateadd(year, Datediff(year, 0, Getdate()) - 2, 0)
AND
Dateadd(year, Datediff(year, 0, Getdate()), -1)
GROUP BY M.homebranch,
M.locationname,month(M.ActiveStart),
year(M.ActiveStart)) AS g1
INNER JOIN (SELECT Count(*)AS No_of_Live_Member,
M.homebranch,
M.locationname,
month(M.ActiveStart) month,
YEAR(M.ActiveStart) year
FROM ax.memberships M
WHERE M.activestart BETWEEN Dateadd(year, Datediff(year, 0, Getdate()) - 2, 0)
AND
Dateadd(year, Datediff(year, 0, Getdate()), -1)
GROUP BY M.homebranch,
M.locationname,
month(M.ActiveStart),
year(M.ActiveStart)
) AS g2
ON g1.homebranch = g2.homebranch
AND g1.locationname = g2.locationname
AND g1.month = g2.month
AND g1.year = g2.year
Order by g1.year,g1.month
Can you please check my query is right or not. Because I wanted to get from last 2 yrs.

How to display monthly balance for month with no balance SQL Server

I have the following block of code which I am using to query a SQL Server database that summarizes all balances for each of the previous 13 months. It works pretty good, but there are a few months when there were no balances to report. These months are not displaying which I do need. At this point, I am at a loss for what to try next.
DECLARE #StartDate DATE, #EndDate DATE;
SELECT
#StartDate = CONVERT(VARCHAR(11), DATEADD(month, -13, GETDATE())),
#EndDate = CONVERT(VARCHAR(11), DATEADD(month, 0, GETDATE()));
;WITH d(d) AS
(
SELECT
DATEADD(MONTH, n, DATEADD(MONTH, DATEDIFF(MONTH, 0, #StartDate), 0))
FROM
(SELECT TOP (DATEDIFF(MONTH, #StartDate, #EndDate) + 1)
n = ROW_NUMBER() OVER (ORDER BY [object_id]) - 1
FROM
sys.all_objects ORDER BY [object_id]) AS n
)
SELECT
FORMAT(d.d, 'MMM yy') AS Purchase_Date,
CAST(ROUND(SUM(lm.BALANCE), 0) AS FLOAT) AS Balance
FROM
d
LEFT OUTER JOIN
dbo.purchases AS lm ON lm.purchase_date >= d.d
AND lm.purchase_date < DATEADD(MONTH, 1, d.d)
WHERE
lm.Buyer_code = 'FirstTime'
AND lm.PROGRAM_ID = 'NewBuyers'
GROUP BY
d.d
ORDER BY
d.d
You are overriding the LEFT JOIN by the where clause, which requires that every row have certain values from the left joined table. In effect it is equivalent to an inner join. You need to allow rows from d to survive into the result, which you can do by using the wanted conditions directly in the LEFT JOIN:
SELECT
FORMAT( d.d, 'MMM yy' ) AS Purchase_Date
, CAST( ROUND( SUM( lm.BALANCE ), 0 ) AS float ) AS Balance
FROM d
LEFT OUTER JOIN DBO.purchases AS lm ON lm.purchase_date >= d.d
AND lm.purchase_date < DATEADD( MONTH, 1, d.d )
AND lm.Buyer_code = 'FirstTime'
AND lm.PROGRAM_ID = 'NewBuyers
GROUP BY
d.d
ORDER BY
d.d

SQL: union multiple single row results sets from the same query

I have a query that, when given a specific date, examines a large dataset (around 36m and growing) and returns an aggregate. Everything is working as expected... However, my end goal is to be able to determine a yearly average of these values. Perhaps my brain is running on empty, but I'm trying to do this dynamically where I don't have to run the query 365 times and then average.....
I need to find the yearly average of the 365 results, per #inst, per #program.
Any pointers in the right direction would be most appreciated.
Query:
USE HCODS
GO
DECLARE #user_date DATETIME
DECLARE #inst VARCHAR(4)
DECLARE #program VARCHAR(4)
SELECT #user_date = '9/30/2016'
SELECT #inst = 'SAC'
SELECT #program = 'PSU';
WITH T AS (
SELECT
B.OFFENDERID
,Institution = I.ORGCOMMONID
,BedUse = B.BEDUSE
,BeginEffectiveDtTm = CAST(B.BEDASSIGNMENTDATE AS DATETIME) + CAST(B.BEDASSIGNMENTTIME AS DATETIME)
,EndEffectiveDtTm = CASE WHEN B.BEDASSIGNMENTSTATUS = 'U' THEN
(CAST(B.INMBEDSTATUSDATE AS DATETIME) + CAST(B.INMBEDSTATUSTIME AS DATETIME)) ELSE NULL END
FROM ODS.BEDASSIGNMENT (NOLOCK) B
INNER JOIN (
SELECT F.PARTYID, I.ORGCOMMONID
FROM ODS.ORGANIZATIONPROF (NOLOCK) AS F
INNER JOIN ODS.ORGANIZATIONPROF (NOLOCK) AS I ON F.ORGAREACODE = I.PARTYID
) AS I ON B.FACILITYWHEREBEDLOCATED = I.PARTYID
WHERE B.BEDASSIGNMENTDATE BETWEEN '1/1/2016' AND '12/31/2016'
AND B.BEDASSIGNMENTSTATUS IN ('U','M')
)
SELECT CAST(#user_date AS DATE)
,T.INSTITUTION
,T.BEDUSE
,COUNT(*)
FROM T
WHERE
(
(
T.BEGINEFFECTIVEDTTM <= DATEADD(second,-1,(#user_date+1))
AND
T.ENDEFFECTIVEDTTM >= #user_date
)
OR T.ENDEFFECTIVEDTTM IS NULL
)
AND T.INSTITUTION = #inst
AND T.BedUse = #program
GROUP BY
T.Institution
,T.BedUse
Result sets (each one obtained by a single running of the query)
Date |Institution |BedUse |Count
-----------|------------|-------|-------
2016-09-30 |SAC |PSU |446
2016-10-01 |SAC |PSU |421
2016-10-02 |SAC |PSU |423
etc......
While it is hard to answer the question of your data without seeing it. I can turn you onto a SQL concept of windowed functions. This in essense is doing an inline grouping to aggregate data. If I have a single set but want to fashion multiple statements over it to see different things, this statement is perfect.
So in an example I am in essence going from the 1st of January of 2015 to today(dynamic as this could be any day even after I post this). I am then picking a random number of 1 to 100 to populate my row of data in my temporary set with. I then can do my aggregate operations on that.
DECLARE #Data TABLE ( Id INT IDENTITY, val INT, dt DATETIME)
DECLARE #Start DATETIME = '1-1-2015'
SET NOCOUNT ON;
WHILE #Start <= GETDATE()
BEGIN
INSERT INTO #Data VALUES (ABS(CHECKSUM(NewId())) % 100, #Start)
SELECT #Start = DATEADD(DAY, 1, #STart)
END
SELECT DISTINCT
SUM(Val) OVER() AS TotalValues
, COUNT(*) OVER() AS rowCounts
, DATEADD(YEAR, DATEDIFF(YEAR, 0, Dt), 0) AS YearDate
, COUNT(*) OVER(PARTITION BY DATEADD(YEAR, DATEDIFF(YEAR, 0, Dt), 0)) AS DaysInYear
, SUM(Val) OVER(PARTITION BY DATEADD(YEAR, DATEDIFF(YEAR, 0, Dt), 0)) AS ValsByYear
, AVG(Val) OVER(PARTITION BY DATEADD(YEAR, DATEDIFF(YEAR, 0, Dt), 0)) AS AVGByYear
, DATEADD(Month, DATEDIFF(Month, 0, Dt), 0) AS MonthDate
, COUNT(*) OVER(PARTITION BY DATEADD(Month, DATEDIFF(Month, 0, Dt), 0)) AS DaysInMonth
, SUM(Val) OVER(PARTITION BY DATEADD(Month, DATEDIFF(Month, 0, Dt), 0)) AS ValsByMonth
, AVG(Val) OVER(PARTITION BY DATEADD(Month, DATEDIFF(MOnth, 0, Dt), 0)) AS AVGByMonth
From #Data

Is there a better way to group date rangers in T-SQL than CASE?

At the moment I'm having to run a lot of SQL queries where the results have to be grouped by date ranges. So far I've been doing it like this:
SELECT COUNT(*)
,CASE
WHEN Don_Date BETWEEN DATEADD(month, - 24, getdate())
AND GETDATE()
THEN 1
WHEN Don_Date BETWEEN DATEADD(month, -48, GETDATE())
AND DATEADD(month, - 24, getdate())
THEN 2
END AS DateRange
FROM #temp
GROUP BY CASE
WHEN Don_Date BETWEEN DATEADD(month, - 24, getdate())
AND GETDATE()
THEN 1
WHEN Don_Date BETWEEN DATEADD(month, -48, GETDATE())
AND DATEADD(month, - 24, getdate())
THEN 2
END
Which works, but it's kind of a pain to write.
I'm having to do this quite a lot, and for a lot of different potential date ranges. Is there a better - as in easier to write/less verbose/more malleable - way of doing this?
You could simplify it with a CTE:
WITH Ranges AS
(
SELECT t.*
,CASE
WHEN Don_Date BETWEEN DATEADD(month, - 24, getdate())
AND GETDATE()
THEN 1
WHEN Don_Date BETWEEN DATEADD(month, -48, GETDATE())
AND DATEADD(month, - 24, getdate())
THEN 2
END AS DateRange
FROM #temp t
)
SELECT Count = COUNT(*), DateRange
FROM Ranges
GROUP BY DateRange
With a join to a virtual values table.
select
rangedesc,COUNT(*)
from
yourtable
left join
(values
(DATEADD(month,-24,getdate()),getdate(), 1),
(DATEADD(month,-48,getdate()),DATEADD(month,-24,getdate()), 2)
) ranges(start,finish,rangedesc)
on yourtable.don_date between ranges.start and ranges.finish
group by rangedesc
If you prefer, you could move the date ranges to a CTE.
Of course, as with all date comparisons, be careful with the borders between two ranges. Compared to your original source code, if a date falls exactly 2 years ago, this method would put it in both ranges, rather than just one.
How about this?
;WITH myDates (DateRange, dtStart, dtEnd)
AS ( SELECT 1, DATEADD(MONTH, -24, GETDATE()), DATEADD(MONTH, 0, GETDATE())
UNION ALL SELECT 2, DATEADD(MONTH, -48, GETDATE()), DATEADD(MONTH, -24, GETDATE())
)
SELECT COUNT(*), DateRange
FROM #temp
JOIN myDates ON don_date BETWEEN dtStart AND dtEnd
GROUP BY DateRange

Resources