Divide results of two queries and obtain result in third query - sql-server

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.

Related

Creating a Calendar table without recursion

I want to create a Calendar Table without using the recursion as I have prepared earlier. How can I achieve this task. All the required columns are mentioned in code below and few other details in code comments.
...........................................................................................................................................................................................................................................................................
DECLARE #StartDate date = '20200101'
DECLARE #CutoffDate date = GETDATE()
;WITH seq(n) AS
(
SELECT 0 UNION ALL SELECT n + 1 FROM seq
WHERE n < DATEDIFF(DAY, #StartDate, #CutoffDate)
),
d(d) AS
(
SELECT DATEADD(DAY, n, #StartDate) FROM seq
),
src AS /*SOURCE TABLE WITH OBJECT DEFINITION*/
(
SELECT
TheDate = CONVERT(date, d),
TheDay = DATEPART(DAY, d),
TheDayName = DATENAME(WEEKDAY, d),
TheWeek = DATEPART(WEEK, d),
TheDayOfWeek = DATEPART(WEEKDAY, d),
TheMonth = DATEPART(MONTH, d),
TheMonthName = DATENAME(MONTH, d),
TheQuarter = Concat('Q',DATEPART(Quarter, d)),
Financial_Year = DATEPART(YEAR, d),
Financial_Quarter=Datepart(QUARTER,d),
TheYear = DATEPART(YEAR, d),
TheFirstOfMonth = DATEFROMPARTS(YEAR(d), MONTH(d), 1),
TheFirstOfFYear = DATEFROMPARTS(YEAR(d), 4, 1),
TheFirstOfYear = DATEFROMPARTS(YEAR(d), 1, 1),
TheLastOfYear = DATEFROMPARTS(YEAR(d), 12, 31),
TheDayOfYear = DATEPART(DAYOFYEAR, d)
FROM d
),
Dimension AS
(
SELECT
TheDate,
TheDay,
TheDayName,
TheDayOfWeek,
TheDayOfWeekInMonth = CONVERT(tinyint, ROW_NUMBER() OVER
(PARTITION BY TheFirstOfMonth, TheDayOfWeek ORDER BY TheDate)),
TheDayOfYear,
TheWeek,
TheFirstOfWeek = DATEADD(DAY, 1 - TheDayOfWeek, TheDate),
TheLastOfWeek = DATEADD(DAY, 6, DATEADD(DAY, 1 - TheDayOfWeek, TheDate)),
TheWeekOfMonth = CONVERT(tinyint, DENSE_RANK() OVER
(PARTITION BY TheYear, TheMonth ORDER BY TheWeek)),
TheMonth,
TheMonthName,
TheFirstOfMonth,
TheLastOfMonth = MAX(TheDate) OVER (PARTITION BY TheYear, TheMonth),
TheFirstOfNextMonth = DATEADD(MONTH, 1, TheFirstOfMonth),
TheLastOfNextMonth = DATEADD(DAY, -1, DATEADD(MONTH, 2, TheFirstOfMonth)),
TheQuarter,
TheFirstOfQuarter = MIN(TheDate) OVER (PARTITION BY TheYear, TheQuarter),
TheLastOfQuarter = MAX(TheDate) OVER (PARTITION BY TheYear, TheQuarter),
TheYear,
TheFirstOfYear = DATEFROMPARTS(TheYear, 1, 1),
TheFirstOfFYear = DATEFROMPARTS(TheYear, 4, 1),
TheLastOfYear,
MMYYYY = CONVERT(char(2), CONVERT(char(8), TheDate, 101))
+ CONVERT(char(4), TheYear),
Financial_Quarter = Datepart(Quarter,DATEADD(MONTH, -3, TheFirstOfMonth)), /*Starting Financial Quarter from April*/
Financial_Year =CASE
WHEN Financial_Quarter = 1 THEN DATEPART(Year,Dateadd(Year,-1,TheFirstofYear)) ELSE THEYEAR END
FROM src
)
SELECT * FROM Dimension
ORDER BY TheDate
OPTION (MAXRECURSION 0);
As I mentioned in the comments, use a Tally. These are significantly faster than a rCTE as they aren't recursive. I use an inline tally here:
DECLARE #StartDate date = '20200101';
DECLARE #CutoffDate date = GETDATE();
/*
; is a terminator, not a "beginingator". It goes at the end of ALL your statements,
not at the start of statements that require the PREVIOUS statement to be properly terminated.
*/
WITH N AS
(SELECT N
FROM (VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL)) N(N)),
Tally AS
(SELECT 0 AS I
UNION ALL
SELECT TOP (DATEDIFF(DAY, #StartDate, #CutoffDate))
ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS I
FROM N N1,N N2,N N3), --Up to 1000 rows. Add more cross joins for more rows
D AS
(SELECT DATEADD(DAY, T.I, #StartDate) AS d
FROM Tally T),
Src AS /*SOURCE TABLE WITH OBJECT DEFINITION*/
(SELECT CONVERT(date, d) AS TheDate,
DATEPART(DAY, d) AS TheDay,
DATENAME(WEEKDAY, d) AS TheDayName,
DATEPART(WEEK, d) AS TheWeek,
DATEPART(WEEKDAY, d) AS TheDayOfWeek,
DATEPART(MONTH, d) AS TheMonth,
DATENAME(MONTH, d) AS TheMonthName,
CONCAT('Q', DATEPART(QUARTER, d)) AS TheQuarter,
DATEPART(YEAR, d) AS Financial_Year,
DATEPART(QUARTER, d) AS Financial_Quarter,
DATEPART(YEAR, d) AS TheYear,
DATEFROMPARTS(YEAR(d), MONTH(d), 1) AS TheFirstOfMonth,
DATEFROMPARTS(YEAR(d), 4, 1) AS TheFirstOfFYear,
DATEFROMPARTS(YEAR(d), 1, 1) AS TheFirstOfYear,
DATEFROMPARTS(YEAR(d), 12, 31) AS TheLastOfYear,
DATEPART(DAYOFYEAR, d) AS TheDayOfYear
FROM d),
Dimension AS
(SELECT TheDate,
TheDay,
TheDayName,
TheDayOfWeek,
CONVERT(tinyint, ROW_NUMBER() OVER (PARTITION BY TheFirstOfMonth, TheDayOfWeek ORDER BY TheDate)) AS TheDayOfWeekInMonth,
TheDayOfYear,
TheWeek,
DATEADD(DAY, 1 - TheDayOfWeek, TheDate) AS TheFirstOfWeek,
DATEADD(DAY, 6, DATEADD(DAY, 1 - TheDayOfWeek, TheDate)) AS TheLastOfWeek,
CONVERT(tinyint, DENSE_RANK() OVER (PARTITION BY TheYear, TheMonth ORDER BY TheWeek)) AS TheWeekOfMonth,
TheMonth,
TheMonthName,
TheFirstOfMonth,
MAX(TheDate) OVER (PARTITION BY TheYear, TheMonth) AS TheLastOfMonth,
DATEADD(MONTH, 1, TheFirstOfMonth) AS TheFirstOfNextMonth,
DATEADD(DAY, -1, DATEADD(MONTH, 2, TheFirstOfMonth)) AS TheLastOfNextMonth,
TheQuarter,
MIN(TheDate) OVER (PARTITION BY TheYear, TheQuarter) AS TheFirstOfQuarter,
MAX(TheDate) OVER (PARTITION BY TheYear, TheQuarter) AS TheLastOfQuarter,
TheYear,
DATEFROMPARTS(TheYear, 1, 1) AS TheFirstOfYear,
DATEFROMPARTS(TheYear, 4, 1) AS TheFirstOfFYear,
TheLastOfYear,
CONVERT(char(2), CONVERT(char(8), TheDate, 101)) + CONVERT(char(4), TheYear) AS MMYYYY,
DATEPART(QUARTER, DATEADD(MONTH, -3, TheFirstOfMonth)) AS Financial_Quarter, /*Starting Financial Quarter from April*/
CASE
WHEN Financial_Quarter = 1 THEN DATEPART(YEAR, DATEADD(YEAR, -1, TheFirstOfYear))
ELSE TheYear
END AS Financial_Year
FROM src)
SELECT *
FROM Dimension
ORDER BY TheDate;

SQL Server update caused Datediff to not work

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

Convert Select Query into CTE

SELECT
COUNT(*) AS Previous_Live_Members, m.HomeBranch, m.LocationName
FROM
AX.Mem M
WHERE
m.ActiveStart < DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()) - 13, 0)
AND (m.ActiveEnd > DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()) - 13, 0) OR M.ActiveEnd IS NULL)
GROUP BY
m.HomeBranch, m.LocationName
I already converted but results are different. Might be some issue in my query. I want to convert simple query into CTE table.
WITH CTE_A AS
(
SELECT
SUM(CASE
WHEN M.ActiveStart < DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()) - 13, 0)
AND M.ActiveEnd > DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()) - 13, 0) OR M.ActiveEnd IS NULL
THEN 1
ELSE 0
END) AS Previous_No_of_Live_Member,
M.HomeBranch,
M.LocationName
FROM
AX.Mem M
GROUP BY
M.HomeBranch, M.LocationName
)
SELECT
Previous_No_of_Live_Member,
HomeBranch,
LocationName
FROM
CTE_A
The CTE version is missing a pair of parenthesis.
You are using a query on ActiveEnd where (ActiveEnd > ... OR ActiveEnd IS NULL). This should be in parenthesis in the CTE version too.
Compare this line
...
and (m.ActiveEnd > DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()) - 13, 0) or M.ActiveEnd is null)
with the CTE version
...
AND
M.ActiveEnd > DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()) - 13, 0)
or M.ActiveEnd is null then 1 else 0 end)
I think it should be (indicated with ^ where I think parenthesis should go):
...
AND
(M.ActiveEnd > DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()) - 13, 0)
^ or M.ActiveEnd is null) then 1 else 0 end)
^

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

Get result by week

I need you for order a query by the date and then if it's possible to simplify it :-)
This query will return the number of entries per week from the current day.
Here is the query :
SELECT CONVERT(VarChar(50), DATEADD(day, DATEDIFF(day, 0, GETDATE()), -7), 103) as periode_join, COUNT(u.usr_ID) as cptu
FROM [USR_USER] u
INNER JOIN [USI_USER_SITE] s ON u.USR_ID = s.USR_ID
WHERE u.[USR_JOINED_DT] >= DATEADD(day, DATEDIFF(day, 0, GETDATE()), -7) and u.[USR_JOINED_DT] <= DATEADD(day, DATEDIFF(day, 0, GETDATE()), 0)
UNION
SELECT CONVERT(VarChar(50), DATEADD(day, DATEDIFF(day, 0, GETDATE()), -14), 103) as periode_join, COUNT(u.usr_ID) as cptu
FROM [USR_USER] u
INNER JOIN [USI_USER_SITE] s ON u.USR_ID = s.USR_ID
WHERE u.[USR_JOINED_DT] >= DATEADD(day, DATEDIFF(day, 0, GETDATE()), -14) and u.[USR_JOINED_DT] <= DATEADD(day, DATEDIFF(day, 0, GETDATE()), -7)
UNION
SELECT CONVERT(VarChar(50), DATEADD(day, DATEDIFF(day, 0, GETDATE()), -21), 103) as periode_join, COUNT(u.usr_ID) as cptu
FROM [USR_USER] u
INNER JOIN [USI_USER_SITE] s ON u.USR_ID = s.USR_ID
WHERE u.[USR_JOINED_DT] >= DATEADD(day, DATEDIFF(day, 0, GETDATE()), -21) and u.[USR_JOINED_DT] <= DATEADD(day, DATEDIFF(day, 0, GETDATE()), -14)
UNION
SELECT CONVERT(VarChar(50), DATEADD(day, DATEDIFF(day, 0, GETDATE()), -28), 103) as periode_join, COUNT(u.usr_ID) as cptu
FROM [USR_USER] u
INNER JOIN [USI_USER_SITE] s ON u.USR_ID = s.USR_ID
WHERE u.[USR_JOINED_DT] >= DATEADD(day, DATEDIFF(day, 0, GETDATE()), -28) and u.[USR_JOINED_DT] <= DATEADD(day, DATEDIFF(day, 0, GETDATE()), -21)
UNION
SELECT CONVERT(VarChar(50), DATEADD(day, DATEDIFF(day, 0, GETDATE()), -35), 103) as periode_join, COUNT(u.usr_ID) as cptu
FROM [USR_USER] u
INNER JOIN [USI_USER_SITE] s ON u.USR_ID = s.USR_ID
WHERE u.[USR_JOINED_DT] >= DATEADD(day, DATEDIFF(day, 0, GETDATE()), -35) and u.[USR_JOINED_DT] <= DATEADD(day, DATEDIFF(day, 0, GETDATE()), -28)
UNION
SELECT CONVERT(VarChar(50), DATEADD(day, DATEDIFF(day, 0, GETDATE()), -42), 103) as periode_join, COUNT(u.usr_ID) as cptu
FROM [USR_USER] u
INNER JOIN [USI_USER_SITE] s ON u.USR_ID = s.USR_ID
WHERE u.[USR_JOINED_DT] >= DATEADD(day, DATEDIFF(day, 0, GETDATE()), -42) and u.[USR_JOINED_DT] <= DATEADD(day, DATEDIFF(day, 0, GETDATE()), -35)
ORDER BY periode_join desc
Here is the result :
periode_join cptu
28/05/2013 8740
25/06/2013 9773
18/06/2013 8212
11/06/2013 6644
04/06/2013 9420
02/07/2013 7868
Thanks a lot :-D
if you have SQL Server 2005 and above, you can try something like this:
;with CTE_Data as
(
select
u.usr_id,
cast(dateadd(dd, -(datediff(dd, u.usr_joined_dt, getdate()) / 7 + 1) * 7, getdate()) as date) as periode_join
from usr_user as u
inner join usi_user_site as s on u.usr_id = s.usr_id
)
select periode_join, count(usr_id) as cptu
from CTE_Data
group by periode_join
order by periode_join asc
SQL FIDDLE EXAMPLE
To split data by weeks we have to take difference in days between getdate() and date from table - datediff(dd, u.usr_joined_dt, getdate()), then we have to get number of whole weeks - / 7, then we have to substract whole number of weeks + 1.
So, for example, if date = '2013/06/30' then number of days = 9, whole number of weeks = 1 and we have to substract 1 + 1 weeks so we get '2013/06/25' and so on

Resources