I am trying to add together the values from two columns that i have previously defined. I was wondering if there was a way to do this within the query.
Below is my Code and i am trying to add together the values of the named columns SP and IP:
DECLARE #Flag nvarchar(10),
#Month int,
#Year int,
#ViewName as nvarchar(50),
#PrePlumb as int
SET #Flag = 'Grid'
SET #Month = 01
SET #Year = 2013
SET #ViewName = 'Delivered'
SELECT PID,
[Customer Name],
[Project Name],
Delivered1,
CAST(SUM(Production) AS decimal(10, 2)) AS Value,
CAST(SUM(SellingPrice) AS decimal(10, 2)) AS SP,
CAST(SUM(IP) AS decimal(10, 2)) AS IP,
CAST(SUM(Plumb) AS Decimal(10, 2)) As Plumb
FROM (
SELECT SpecificationHeader.Qno,
SpecificationHeader.PID,
Customers3.[Customer Name],
Projects2.[Project Name],
MAX(SpecDetailsExt.Delivered) AS Delivered1,
MAX(SpecDetails.SellingPrice) AS SellingPrice,
MAX(SpecDetails.FactoryRate) AS Production,
(CASE
WHEN MAX(SpecificationHeader.[Installation Costs]) = 'Yes'
THEN MAX(specdetails.InstallationCostPlusMargin) ELSE 0
END) AS IP,
(CASE
WHEN MAX(SpecificationHeader.[Plumbing Costs]) = 'Yes'
THEN MAX(specdetails.PlumbCostPlusMargin) ELSE 0
END) AS Plumb,
MAX(CONVERT(date, SpecDetailsExt.Delivered, 3)) AS Delivered
FROM SpecDetailsExt
INNER JOIN SpecDetails
ON SpecDetailsExt.SrecId = SpecDetails.SrecId
INNER JOIN SpecificationHeader
ON SpecDetails.QuoteNo = SpecificationHeader.Qno
INNER JOIN Projects2
ON SpecificationHeader.PID = Projects2.PID
INNER JOIN Customers3
ON Projects2.[Customer Number] = Customers3.[Customer Number]
WHERE (SpecificationHeader.MoveToOrder <> '')
AND (SpecDetailsExt.Delivered <> N'')
AND (DATEPART(MONTH, CONVERT(date, SpecDetailsExt.Delivered , 3)) = #Month)
AND (YEAR(CONVERT(date, SpecDetailsExt.Delivered , 3)) = #Year)
GROUP BY SpecificationHeader.Qno,
Customers3.[Customer Name],
Projects2.[Project Name],
SpecificationHeader.PID,
SpecDetailsExt.SrecId
) AS x
GROUP BY PID,
[Customer Name],
[Project Name],
Delivered1
ORDER BY Delivered1 desc,
[Customer Name],
[Project Name]
Use a CTE:
DECLARE #Flag nvarchar(10),
#Month int,
#Year int,
#ViewName as nvarchar(50),
#PrePlumb as int
SET #Flag = 'Grid'
SET #Month = 01
SET #Year = 2013
SET #ViewName = 'Delivered'
;WITH MyCTE AS
(
SELECT PID,
[Customer Name],
[Project Name],
Delivered1,
CAST(SUM(Production) AS decimal(10, 2)) AS Value,
CAST(SUM(SellingPrice) AS decimal(10, 2)) AS SP,
CAST(SUM(IP) AS decimal(10, 2)) AS IP,
CAST(SUM(Plumb) AS Decimal(10, 2)) As Plumb
FROM (
SELECT SpecificationHeader.Qno,
SpecificationHeader.PID,
Customers3.[Customer Name],
Projects2.[Project Name],
MAX(SpecDetailsExt.Delivered) AS Delivered1,
MAX(SpecDetails.SellingPrice) AS SellingPrice,
MAX(SpecDetails.FactoryRate) AS Production,
(CASE
WHEN MAX(SpecificationHeader.[Installation Costs]) = 'Yes'
THEN MAX(specdetails.InstallationCostPlusMargin) ELSE 0
END) AS IP,
(CASE
WHEN MAX(SpecificationHeader.[Plumbing Costs]) = 'Yes'
THEN MAX(specdetails.PlumbCostPlusMargin) ELSE 0
END) AS Plumb,
MAX(CONVERT(date, SpecDetailsExt.Delivered, 3)) AS Delivered
FROM SpecDetailsExt
INNER JOIN SpecDetails
ON SpecDetailsExt.SrecId = SpecDetails.SrecId
INNER JOIN SpecificationHeader
ON SpecDetails.QuoteNo = SpecificationHeader.Qno
INNER JOIN Projects2
ON SpecificationHeader.PID = Projects2.PID
INNER JOIN Customers3
ON Projects2.[Customer Number] = Customers3.[Customer Number]
WHERE (SpecificationHeader.MoveToOrder <> '')
AND (SpecDetailsExt.Delivered <> N'')
AND (DATEPART(MONTH, CONVERT(date, SpecDetailsExt.Delivered , 3)) = #Month)
AND (YEAR(CONVERT(date, SpecDetailsExt.Delivered , 3)) = #Year)
GROUP BY SpecificationHeader.Qno,
Customers3.[Customer Name],
Projects2.[Project Name],
SpecificationHeader.PID,
SpecDetailsExt.SrecId
) AS x
GROUP BY PID,
[Customer Name],
[Project Name],
Delivered1
ORDER BY Delivered1 desc,
[Customer Name],
[Project Name]
)
SELECT PID,
[Customer Name],
[Project Name],
Delivered1,
Value,
SP,
IP,
Plumb,
SP + IP AS Combined
FROM MyCTE
Related
I found in our database a cursor statement and I would like to replace it.
Declare #max_date datetime
Select #max_date = max(finished) From Payments
Declare #begin_date datetime = '2015-02-01'
Declare #end_of_last_month datetime
While #begin_date <= #max_date
Begin
SELECT #end_of_last_month = CAST(DATEADD(DAY, -1 , DATEFROMPARTS(YEAR(#begin_date),MONTH(#begin_date),1)) AS DATE) --AS end_of_last_month
Insert Into #table(Customer, ArticleTypeID, ArticleType, end_of_month, month, year)
Select Count(distinct (customerId)), prod.ArticleTypeID, at.ArticleType, #end_of_last_month, datepart(month, #end_of_last_month), datepart(year, #end_of_last_month)
From Customer cust
Inner join Payments pay ON pay.member_id = m.member_id
Inner Join Products prod ON prod.product_id = pay.product_id
Inner Join ArticleType at ON at.ArticleTypeID = prod.ArticleTypeID
Where #end_of_last_month between begin_date and expire_date
and completed = 1
Group by prod.ArticleTypeID, at.ArticleType
order by prod.ArticleTypeID, at.ArticleType
Set #begin_date = DATEADD(month, 1, #begin_date)
End
It groups all User per Month where the begin- and expire date in the actual Cursormonth.
Notes:
The user has different payment types, for e.g. 1 Month, 6 Month and so on.
Is it possible to rewrite the code - my problem is only the identification at the where clause (#end_of_last_month between begin_date and expire_date)
How can I handle this with joins or cte's?
What you need first, if not already is a numbers table
Using said Numbers table you can create a dynamic list of dates for "end_of_Last_Month" like so
;WITH ctexAllDates
AS (
SELECT end_of_last_month = DATEADD(DAY, -1, DATEADD(MONTH, N.N -1, #begin_date))
FROM
dbo.Numbers N
WHERE
N.N <= DATEDIFF(MONTH, #begin_date, #max_date) + 1
)
select * FROM ctexAllDates
Then combine with your query like so
;WITH ctexAllDates
AS (
SELECT end_of_last_month = DATEADD(DAY, -1, DATEADD(MONTH, N.N -1, #begin_date))
FROM
dbo.Numbers N
WHERE
N.N <= DATEDIFF(MONTH, #begin_date, #max_date) + 1
)
INSERT INTO #table
(
Customer
, ArticleTypeID
, ArticleType
, end_of_month
, month
, year
)
SELECT
COUNT(DISTINCT (customerId))
, prod.ArticleTypeID
, at.ArticleType
, A.end_of_last_month
, DATEPART(MONTH, A.end_of_last_month)
, DATEPART(YEAR, A.end_of_last_month)
FROM
Customer cust
INNER JOIN Payments pay ON pay.member_id = m.member_id
INNER JOIN Products prod ON prod.product_id = pay.product_id
INNER JOIN ArticleType at ON at.ArticleTypeID = prod.ArticleTypeID
LEFT JOIN ctexAllDates A ON A.end_of_last_month BETWEEN begin_date AND expire_date
WHERE completed = 1
GROUP BY
prod.ArticleTypeID
, at.ArticleType
, A.end_of_last_month
ORDER BY
prod.ArticleTypeID
, at.ArticleType;
In this query I cant understand what would be the proper syntax to PIVOT it by month and also display just top 10 records based on SUM(NetWrittenPremium).
;with cte_TopClasses
AS (
select
b.YearNum,
b.MonthNum,
REPLACE(ClassCode,'+','') + ' - '+ QLL.Description as Description,
SUM( Premium) as NetWrittenPremium
FROM tblCalendar b
LEFT JOIN ProductionReportMetrics prm ON b.MonthNum=Month(prm.EffectiveDate) AND b.YearNum = YEAR(EffectiveDate)
AND prm.EffectiveDate >=DateAdd(yy, -1, DATEADD(d, 1, EOMONTH(GETDATE()))) AND prm.EffectiveDate <= EOMONTH(GETDATE()) AND CompanyLine = 'Ironshore Insurance Company'
LEFT JOIN NetRate_Quote_Insur_Quote Q ON prm.NetRate_QuoteID = Q.QuoteID
LEFT JOIN NetRate_Quote_Insur_Quote_Locat QL ON Q.QuoteID = QL.QuoteID
LEFT JOIN (SELECT * FROM NetRate_Quote_Insur_Quote_Locat_Liabi nqI
JOIN ( SELECT LocationID as LocID, MAX(ClassCode) as ClCode
FROM NetRate_Quote_Insur_Quote_Locat_Liabi GROUP BY LocationID ) nqA
ON nqA.LocID = nqI.LocationID AND nqA.ClCode = nqI.ClassCode ) QLL
ON QLL.LocationID = QL.LocationID
WHERE ( b.YearNum = YEAR(GETDATE())-1 and b.MonthNum >= MONTH(GETDATE())+1 ) OR
( b.YearNum = YEAR(GETDATE()) and b.MonthNum <= MONTH(GETDATE()) )
GROUP BY b.YearNum,b.MonthNum,ClassCode, QLL.Description
)
SELECT
--TOP 10
RANK() OVER (ORDER BY NetWrittenPremium DESC) AS Rank, *
FROM cte_TopClasses
WHERE Description IS NOT NULL
ORDER BY NetWrittenPremium DESC,YearNum,MonthNum
The result should look something like that:
If I use the query below and then using matrics in SSRS to PIVOT it - then after grouping by Description it only displays me 2 Description.
;with cte_TopClasses
AS (
select
b.YearNum,
b.MonthNum,
REPLACE(ClassCode,'+','') + ' - '+ QLL.Description as Description,
SUM( Premium) as NetWrittenPremium
FROM tblCalendar b
LEFT JOIN ProductionReportMetrics prm ON b.MonthNum=Month(prm.EffectiveDate) AND b.YearNum = YEAR(EffectiveDate)
AND prm.EffectiveDate >=DateAdd(yy, -1, DATEADD(d, 1, EOMONTH(GETDATE()))) AND prm.EffectiveDate <= EOMONTH(GETDATE()) AND CompanyLine = 'Ironshore Insurance Company'
LEFT JOIN NetRate_Quote_Insur_Quote Q ON prm.NetRate_QuoteID = Q.QuoteID
LEFT JOIN NetRate_Quote_Insur_Quote_Locat QL ON Q.QuoteID = QL.QuoteID
LEFT JOIN (SELECT * FROM NetRate_Quote_Insur_Quote_Locat_Liabi nqI
JOIN ( SELECT LocationID as LocID, MAX(ClassCode) as ClCode
FROM NetRate_Quote_Insur_Quote_Locat_Liabi GROUP BY LocationID ) nqA
ON nqA.LocID = nqI.LocationID AND nqA.ClCode = nqI.ClassCode ) QLL
ON QLL.LocationID = QL.LocationID
WHERE ( b.YearNum = YEAR(GETDATE())-1 and b.MonthNum >= MONTH(GETDATE())+1 ) OR
( b.YearNum = YEAR(GETDATE()) and b.MonthNum <= MONTH(GETDATE()) )
GROUP BY b.YearNum,b.MonthNum,ClassCode, QLL.Description
)
SELECT *
FROM (SELECT RANK() OVER (ORDER BY NetWrittenPremium DESC) AS Rank, *
FROM cte_TopClasses
WHERE Description IS NOT NULL) AA
WHERE AA.Rank <= 10
ORDER BY AA.NetWrittenPremium DESC, AA.YearNum, AA.MonthNum
And the result of it in SSRS matrics :
You could try something like this at the end of the query, rather than what is there now:
SELECT *
FROM (SELECT RANK() OVER (ORDER BY [Description] DESC) AS Rank, *
FROM cte_TopClasses
WHERE Description IN (SELECT [Description]
FROM (SELECT RANK() OVER (ORDER BY SUM(NetWrittenPremium) DESC) AS [Rank], [Description], SUM(NetWrittenPremium) AS total
FROM cte_TopClasses
WHERE [Description] IS NOT NULL
GROUP BY [Description]) BB
WHERE [Rank] <= 10)) AA
ORDER BY YearNum, MonthNum
This wraps the query in a SELECT, and filters the ranked results to the 10 you want.
Then use a matrix in the report to pivot the results.
I am trying to group by month to separate my result set into monthly breakdowns, but I want to display the month name instead of the month number.
SELECT
DATEPART(MONTH, R.received_date) AS [Month],
--DATENAME( MONTH, DATEPART( MONTH, R.received_date)) AS [Month] ,
o.name AS [CountyName] ,
rsc.description AS [Filing],
COUNT(*) AS [Total]
FROM dbo.requests AS [r]
INNER JOIN dbo.organizations AS [o] ON o.id = r.submitted_to_organiztion_id
INNER JOIN dbo.request_status_codes AS [rsc] ON rsc.code = r.request_status_code
WHERE r.submitted_to_organiztion_id < 68
AND r.request_type_code = 1
AND CAST(r.received_date AS DATE) >= '01/01/2016'
AND CAST(r.received_date AS DATE) <= '06/30/2016'
AND o.name = 'Alachua'
GROUP BY
DATEPART(MONTH, R.received_date) ,
--DATENAME( MONTH, DATEPART( MONTH, R.received_date)) ,
o.name ,
rsc.description;
And the results are expected below:
But if I group by DATENAME, the results are not what I would expect from the query below:
SELECT
--DATEPART(MONTH, R.received_date) AS [Month],
DATENAME( MONTH, DATEPART( MONTH, R.received_date)) AS [Month] ,
o.name AS [CountyName] ,
rsc.description AS [Filing],
COUNT(*) AS [Total]
FROM dbo.requests AS [r]
INNER JOIN dbo.organizations AS [o] ON o.id = r.submitted_to_organiztion_id
INNER JOIN dbo.request_status_codes AS [rsc] ON rsc.code = r.request_status_code
WHERE r.submitted_to_organiztion_id < 68
AND r.request_type_code = 1
AND CAST(r.received_date AS DATE) >= '01/01/2016'
AND CAST(r.received_date AS DATE) <= '06/30/2016'
AND o.name = 'Alachua'
GROUP BY
--DATEPART(MONTH, R.received_date) ,
DATENAME( MONTH, DATEPART( MONTH, R.received_date)) ,
o.name ,
rsc.description
ORDER BY
[Month] ,
CountyName ,
Filing
when 6 months become grouped into one set - January:
What can I do to fix the query to display the first result set but with the month name instead of numeric value?
Thanks,
I am trying to modify my query to include a running total for each county in my report. Below is my working query with an attempt to use SUM OVER PARTITION commented out:
SELECT DATEPART(MONTH, r.received_date) AS [MonthID] ,
DATENAME(MONTH, r.received_date) AS [Month] ,
o.name AS [CountyName] ,
rsc.description AS [Filing] ,
COUNT(r.id) AS [Request_Total] ,
CAST (AVG(CAST (DATEDIFF(HOUR, received_date, completion_date) AS DECIMAL(8,2))) / 24 AS DECIMAL(8,2)) AS [Total_Time_Days]
--SUM(r.id) OVER (PARTITION BY o.name) AS [TotalFilings]
FROM dbo.requests AS [r]
INNER JOIN dbo.organizations AS [o] ON o.id = r.submitted_to_organiztion_id
INNER JOIN dbo.request_status_codes AS [rsc] ON rsc.code = r.request_status_code
WHERE r.submitted_to_organiztion_id < 68
AND r.request_type_code = 1
AND CAST(r.received_date AS DATE) >= '01/01/2016'
AND CAST(r.received_date AS DATE) <= '06/30/2016'
AND o.name = 'Alachua'
GROUP BY DATENAME(MONTH, r.received_date) ,
DATEPART(MONTH, r.received_date) ,
o.name ,
rsc.description
ORDER BY DATEPART(MONTH, r.received_date) ,
CountyName ,
Filing;
And the results look correct:
Perhaps I am misusing the SUM PARTITION BYbut my end goal is to add an additional column that will sum the filing types for each county by month.
For example, the additional column for the month of January should be 13,654 while February should be 14,238 and so on.
Could I get some advice on how to get this query working correctly? Thanks,
Not sure this is the best way or more efficient, but I was able to create a sub-query to obtain the results I wanted. I do believe a CTE or use of a Windows function would be better, but I haven't been able to get it to work. Here is my query however:
SELECT X.[MonthID] ,
X.[Month] ,
X.[CountyName] ,
X.[Filing] ,
X.[Avg_Time_Days] ,
SUM(X.Request_Total) AS [Total_Requests]
FROM ( SELECT DATEPART(MONTH, r.received_date) AS [MonthID] ,
DATENAME(MONTH, r.received_date) AS [Month] ,
o.name AS [CountyName] ,
rsc.description AS [Filing] ,
COUNT(r.id) AS [Request_Total] ,
CAST (AVG(CAST (DATEDIFF(HOUR, received_date,
completion_date) AS DECIMAL(8, 2)))
/ 24 AS DECIMAL(8, 2)) AS [Avg_Time_Days]
--, SUM(r.id) OVER (PARTITION BY o.name, rsc.description) AS [TotalFilings]
FROM dbo.requests AS [r]
INNER JOIN dbo.organizations AS [o] ON o.id = r.submitted_to_organiztion_id
INNER JOIN dbo.request_status_codes AS [rsc] ON rsc.code = r.request_status_code
WHERE r.submitted_to_organiztion_id < 68
AND r.request_type_code = 1
AND CAST(r.received_date AS DATE) >= '01/01/2016'
AND CAST(r.received_date AS DATE) <= '06/30/2016'
--AND o.name = 'Alachua'
GROUP BY DATENAME(MONTH, r.received_date) ,
DATEPART(MONTH, r.received_date) ,
o.name ,
rsc.description
--, r.id
--ORDER BY DATEPART(MONTH, r.received_date) ,
-- CountyName ,
-- Filing
) AS X
GROUP BY X.[MonthID] ,
X.[Month] ,
X.[CountyName] ,
X.[Filing] ,
X.[Avg_Time_Days]
ORDER BY X.[MonthID] ,
X.[Month] ,
X.[CountyName] ,
X.[Filing];
I have a table with date range an i need the sum of overlapping periods (in hours) between its rows.
This is a schema example:
create table period (
id int,
starttime datetime,
endtime datetime,
type varchar(64)
);
insert into period values (1,'2013-04-07 8:00','2013-04-07 13:00','Work');
insert into period values (2,'2013-04-07 14:00','2013-04-07 17:00','Work');
insert into period values (3,'2013-04-08 8:00','2013-04-08 13:00','Work');
insert into period values (4,'2013-04-08 14:00','2013-04-08 17:00','Work');
insert into period values (5,'2013-04-07 10:00','2013-04-07 11:00','Holyday'); /* 1h overlapping with 1*/
insert into period values (6,'2013-04-08 10:00','2013-04-08 20:00','Transfer'); /* 6h overlapping with 3 and 4*/
insert into period values (7,'2013-04-08 11:00','2013-04-08 12:00','Test'); /* 1h overlapping with 3 and 6*/
And its fiddle: http://sqlfiddle.com/#!6/9ca31/10
I expect a sum of 8h overlapping hours:
1h (id 5 over id 1)
6h (id 6 over id 3 and 4)
1h (id 7 over id 3 and 6)
I check this: select overlapping datetime events with SQL but seems to not do what I need.
Thank you.
select sum(datediff(hh, case when t2.starttime > t1.starttime then t2.starttime else t1.starttime end,
case when t2.endtime > t1.endtime then t1.endtime else t2.endtime end))
from period t1
join period t2 on t1.id < t2.id
where t2.endtime > t1.starttime and t2.starttime < t1.endtime;
Updated to handle several overlaps:
select sum(datediff(hh, start, fin))
from (select distinct
case when t2.starttime > t1.starttime then t2.starttime else t1.starttime end as start,
case when t2.endtime > t1.endtime then t1.endtime else t2.endtime end as fin
from period t1
join period t2 on t1.id < t2.id
where t2.endtime > t1.starttime and t2.starttime < t1.endtime
) as overlaps;
I have some "dirty" solution. Hope this helps :)
with src as (
select
convert(varchar, starttime, 112) [start_date]
, cast(left(convert(varchar, starttime, 108), 2) as int) [start_time]
, convert(varchar, endtime, 112) [end_date]
, cast(left(convert(varchar, endtime, 108), 2) as int) [end_time]
, id
from [period]),
[gr] as (
select
row_number() over(order by s1.[start_date], s1.[start_time], s1.[end_time], s2.[start_time], s2.[end_time]) [no]
, s1.[start_date] [date]
, s1.[start_time] [t1]
, s1.[end_time] [t2]
, s2.[start_time] [t3]
, s2.[end_time] [t4]
from src s1
join src s2 on s1.[start_date] = s2.[start_date]
and s1.[end_date] = s2.[end_date]
and (s1.[start_time] between s2.[start_time] and s2.[end_time] or s1.[end_time] between s2.[start_time] and s2.[end_time])
and s1.id != s2.id),
[raw] as (
select [no], [date], [t1] [h] from [gr] union all
select [no], [date], [t2] from [gr] union all
select [no], [date], [t3] from [gr] union all
select [no], [date], [t4] from [gr]),
[max_min] as (
select [no], [date], max(h) [max_h], min(h) [min_h]
from [raw]
group by [no], [date]
),
[result] as (
select [raw].*
from [raw]
left join [max_min] on [raw].[no] = [max_min].[no]
and ([raw].h = [max_min].[max_h] or [raw].h = [max_min].[min_h])
where [max_min].[no] is null),
[final] as (
select distinct r1.[date], r1.h [start_h], r2.h [end_h], abs(r1.h - r2.h) [dif]
from [result] r1
join [result] r2 on r1.[no] = r2.[no]
where abs(r1.h - r2.h) > 0
and r1.h > r2.h)
select sum(dif) [overlapping hours] from [final]
SQLFiddle