I have 2 separate queries that i'd like to combine so that the results for both queries are output to 1 table
From the 2 queries below I'd like one table with the following columns:
StaffId, FullName, DayCount, MonthCount.
What is the best way of doing this?
SELECT TOP (10) COUNT(*) AS MonthCount, Staff.FirstName + Staff.LastName AS FullName, Staff.StaffID
FROM Sales INNER JOIN
Staff ON Sales.StaffID = Staff.StaffID LEFT OUTER JOIN
SaleEndorsements ON Sales.SaleID = SaleEndorsements.SaleID
WHERE Sales.CreationDate BETWEEN DATEADD(mm, DATEDIFF(mm,'',getdate()), '') AND getdate() AND SaleEndorsements.EndorsementID = 31
GROUP BY Staff.FirstName, Staff.LastName, Staff.StaffID
ORDER BY MonthCount DESC
SELECT TOP (10) COUNT(*) AS DayCount, Staff.FirstName + Staff.LastName AS FullName, Staff.StaffID
FROM Sales INNER JOIN
Staff ON Sales.StaffID = Staff.StaffID LEFT OUTER JOIN
SaleEndorsements ON Sales.SaleID = SaleEndorsements.SaleID
WHERE Sales.CreationDate BETWEEN DATEADD(DD, DATEDIFF(DD,'',getdate()), '') AND getdate() AND SaleEndorsements.EndorsementID = 31
GROUP BY Staff.FirstName, Staff.LastName, Staff.StaffID
ORDER BY DayCount DESC
Untested and so may be riddled with syntax errors but I think you need to do something like
Push the repeated functionality into a base CTE
Create another CTE with the month count referencing (1)
Create another CTE with the day count referencing (1)
Full Outer Join (2) and (3)
Additionally your WHERE clause makes the LEFT JOIN pointless so I've changed this to an INNER JOIN.
WITH T
AS (SELECT Staff.FirstName,
Staff.LastName,
Staff.StaffID,
Sales.CreationDate
FROM Sales
INNER JOIN Staff
ON Sales.StaffID = Staff.StaffID
INNER JOIN SaleEndorsements
ON Sales.SaleID = SaleEndorsements.SaleID
WHERE SaleEndorsements.EndorsementID = 31),
D
AS (SELECT TOP (10) COUNT(*) AS DayCount,
FirstName + LastName AS FullName,
StaffID
FROM T
WHERE CreationDate BETWEEN DATEADD(DD, DATEDIFF(DD, '', getdate()), '') AND
getdate()
GROUP BY FirstName,
LastName,
StaffID
ORDER BY DayCount DESC),
M
AS (SELECT TOP (10) COUNT(*) AS MonthCount,
FirstName + LastName AS FullName,
FROM T
WHERE CreationDate BETWEEN DATEADD(mm, DATEDIFF(mm, '', getdate()), '') AND
getdate()
GROUP BY FirstName,
LastName,
StaffID
ORDER BY MonthCount DESC)
SELECT ISNULL(M.StaffId, D.StaffId) AS StaffId,
ISNULL(M.FullName, D.FullName) AS FullName,
M.MonthCount,
D.DayCount
FROM M
FULL OUTER JOIN D
ON M.StaffID = D.StaffID
Add a UNION ALL clause to this, like so:
SELECT TOP (10) COUNT(*) AS MonthCount, Staff.FirstName + Staff.LastName AS FullName, Staff.StaffID FROM Sales INNER JOIN Staff ON Sales.StaffID = Staff.StaffID LEFT OUTER JOIN SaleEndorsements ON Sales.SaleID = SaleEndorsements.SaleID WHERE Sales.CreationDate BETWEEN DATEADD(mm, DATEDIFF(mm,'',getdate()), '') AND getdate() AND SaleEndorsements.EndorsementID = 31 GROUP BY Staff.FirstName, Staff.LastName, Staff.StaffID ORDER BY MonthCount DESC
union all
SELECT TOP (10) COUNT(*) AS DayCount, Staff.FirstName + Staff.LastName AS FullName, Staff.StaffID FROM Sales INNER JOIN Staff ON Sales.StaffID = Staff.StaffID LEFT OUTER JOIN SaleEndorsements ON Sales.SaleID = SaleEndorsements.SaleID WHERE Sales.CreationDate BETWEEN DATEADD(DD, DATEDIFF(DD,'',getdate()), '') AND getdate() AND SaleEndorsements.EndorsementID = 31 GROUP BY Staff.FirstName, Staff.LastName, Staff.StaffID ORDER BY DayCount DESC
If you can use a stored procedure, this would be a way of doing it:
CREATE PROCEDURE [dbo].[GetStats]
AS
SELECT TOP (10) Staff.StaffID, Staff.FirstName + Staff.LastName AS FullName, COUNT(*) AS MonthCount, 0 As DayCount
INTO #TempMonthlyStats
FROM Sales INNER JOIN
Staff ON Sales.StaffID = Staff.StaffID LEFT OUTER JOIN
SaleEndorsements ON Sales.SaleID = SaleEndorsements.SaleID
WHERE Sales.CreationDate BETWEEN DATEADD(mm, DATEDIFF(mm,'',getdate()), '') AND getdate() AND SaleEndorsements.EndorsementID = 31
GROUP BY Staff.FirstName, Staff.LastName, Staff.StaffID
ORDER BY MonthCount DESC
SELECT TOP (10) Staff.StaffID, Staff.FirstName + Staff.LastName AS FullName, 0 AS MonthCount, COUNT(*) As DayCount
INTO #TempDailyStats
FROM Sales INNER JOIN
Staff ON Sales.StaffID = Staff.StaffID LEFT OUTER JOIN
SaleEndorsements ON Sales.SaleID = SaleEndorsements.SaleID
WHERE Sales.CreationDate BETWEEN DATEADD(DD, DATEDIFF(DD,'',getdate()), '') AND getdate() AND SaleEndorsements.EndorsementID = 31
GROUP BY Staff.FirstName, Staff.LastName, Staff.StaffID
ORDER BY MonthCount DESC
SELECT #TempMonthlyStats.StaffID, #TempMonthlyStats.FullName, #TempMonthlyStats.MonthCount, COALESCE(#TempDailyStats.DayCount,0) AS DayCount
FROM #TempMonthlyStats
LEFT OUTER JOIN #TempDailyStats
ON #TempMonthlyStats.StaffID = #TempDailyStats.StaffID
ORDER BY MonthCount DESC
Related
why does this query miscalculates the colum for ordertaken?? is it about the groupings>
SELECT t2.employeeid, t1.firstname || ' ' || t1.lastname as fullname,
sum(t3.quantity*t4.price) as totalsales,
COUNT(t2.orderid) AS ordertaken, COUNT(DISTINCT t2.customerid) AS uniquecustomercount
from employees as t1
join orders as t2 on t2.employeeid = t1.employeeid
join order_details as t3 on t2.orderid = t3.orderid
join products as t4 on t4.productid = t3.productid
group by t2.employeeid, fullname
correct computation for column ordertaken
If I understand correctly, you need a distinct count for both counts:
SELECT
t2.employeeid,
t1.firstname || ' ' || t1.lastname AS fullname,
SUM(t3.quantity*t4.price) AS totalsales,
COUNT(DISTINCT t2.orderid) AS ordertaken,
COUNT(DISTINCT t2.customerid) AS uniquecustomercount
FROM employees AS t1
INNER JOIN orders AS t2 ON t2.employeeid = t1.employeeid
INNER JOIN order_details AS t3 ON t2.orderid = t3.orderid
INNER JOIN products AS t4 ON t4.productid = t3.productid
GROUP BY t2.employeeid, fullname;
The distinct counts are required on the counts from the orders table because the joins to order_details and products may duplicate a given order record, magnifying the count.
I have a query like this:
select c.id, c.name, c.website, c.longdescription, c.description, c.email,
(SELECT jsonb_agg(ev) FROM
(SELECT ev.title, ev.description, ev.longdescription,
(SELECT jsonb_agg(ed) FROM
(SELECT ed.startdate, ed.enddate, ed.id WHERE ed.id notnull)ed) as dates, ev.id WHERE ev.id notnull) ev) as events,
(SELECT jsonb_agg(ca) FROM (SELECT ct.zip, ca.id, ca.street1, ca.street2, ca.addresstype_id, ST_Y(ca.geopoint::geometry) as latitude, ST_X(ca.geopoint::geometry) as longitude
WHERE ca.id notnull)ca) as addresses
FROM companies c
LEFT JOIN events ev ON ev.company_id = c.id
LEFT JOIN companyaddresses ca ON ca.company_id = c.id
LEFT JOIN cities ct ON ct.id = ca.city_id
LEFT JOIN eventdates ed ON ed.event_id = ev.id
GROUP by c.id
I am getting the error "ERROR: subquery uses ungrouped column "ev.title" from
outer query Position: 125".
Can't figure out how to group it correctly for the subqueries. Any suggestions?
Give this a try:
SELECT c.id, c.name, c.website, c.longdescription, c.description, c.email,
(SELECT jsonb_agg(ev) FROM
(SELECT even.title, even.description, even.longdescription,
(SELECT jsonb_agg(ed) FROM
(SELECT eventdates.startdate, eventdates.enddate, eventdates.id FROM eventdates WHERE eventdates.event_id = even.id)ed) as dates,
even.id FROM events even WHERE even.company_id = c.id) ev) as events,
jsonb_agg((SELECT ca FROM (SELECT ct.zip, ca.id, ca.street1, ca.street2, ca.addresstype_id, ST_Y(ca.geopoint::geometry) as latitude, ST_X(ca.geopoint::geometry) as longitude WHERE ca.id notnull)ca)) as addresses
FROM companies c
LEFT JOIN companyaddresses ca ON ca.company_id = c.id
LEFT JOIN cities ct ON ct.id = ca.city_id
Group by c.id
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'd like to rewrite the following select statement without the sub selects; while it works at the moment as it is it only works if there's data, when one of the sub selects doesn't return data I get an error
Each GROUP BY expression must contain at least one column that is not an outer reference.
This is the select:
SELECT COUNT(DISTINCT ( PROMSID )) AS Volume ,
( SELECT CAST(CAST(COUNT(DISTINCT ( PROMSID )) AS DECIMAL(8, 2))
/ ( SELECT COUNT(DISTINCT RES.Branch)
FROM tblPROMsExportSummary AS PES
INNER JOIN TVF_GetRelevantScorecards(#ProcedureID, 82, #StartDate, #EndDate) AS RES ON RES.PROMSID = PES.PROMSID
INNER JOIN tblUploadedScorecards AS UPL ON PES.PROMSID = UPL.PEMSID
WHERE RES.[Month] = TVF.MonthValue
GROUP BY TVF.MonthValue
) AS DECIMAL(8, 2)) AS PCTAverage
FROM #RelevantSummaryPCT AS PCT
WHERE PCT.[Month] = TVF.[MonthValue]
GROUP BY TVF.[MonthValue]
) AS PCTAverage ,
TVF.ShortMonth AS [Month]
FROM #RelevantSummary AS RS
RIGHT OUTER JOIN TVF_Months(#StartDate, #EndDate) AS TVF ON TVF.MonthValue = RS.[Month]
GROUP BY TVF.[MonthName] ,
TVF.[MonthValue] ,
TVF.ShortMonth ,
TVF.DisplayOrder
ORDER BY TVF.DisplayOrder
What I am looking to achieve is a a single set of data from 2 temp tables which store results for different levels of reporting. The Volume column is the volume of results for 'my group' and the PCTAverage is the volume of results across all groups. The selects for those 2 temp tables:
SELECT DISTINCT
PES.FKProcedureID ,
PES.PROMSID ,
UPL.PKID AS UploadID ,
MONTH(UPL.ShopDate) AS [Month]
INTO #RelevantSummary
FROM tblPROMsExportSummary AS PES
INNER JOIN TVF_GetRelevantScorecards(#ProcedureID, #AreaID, #StartDate, #EndDate) AS RES ON RES.PROMSID = PES.PROMSID
INNER JOIN tblUploadedScorecards AS UPL ON PES.PROMSID = UPL.PEMSID
-- also get them for all PCTs, #AreaID hardcoded to 82
SELECT DISTINCT
PES.FKProcedureID ,
PES.PROMSID ,
UPL.PKID AS UploadID ,
MONTH(UPL.ShopDate) AS [Month]
INTO #RelevantSummaryPCT
FROM tblPROMsExportSummary AS PES
INNER JOIN TVF_GetRelevantScorecards(#ProcedureID, 82, #StartDate, #EndDate) AS RES ON RES.PROMSID = PES.PROMSID
INNER JOIN tblUploadedScorecards AS UPL ON PES.PROMSID = UPL.PEMSID
I'm not as good as to rewrite the sub queries, but based on what you wrote :
I'd like to rewrite the following select statement without the sub selects;
while it works at the moment as it is it only works if there's data, when one of the sub selects doesn't return data I get an error
I wonder if COALESCE could do the trick for your problem.
Using derived tables is what I was after, in the example above it can be achieved like this:
SELECT * FROM (
SELECT DISTINCT
PES.FKProcedureID ,
PES.PROMSID ,
UPL.PKID AS UploadID ,
MONTH(UPL.ShopDate) AS [Month]
INTO #RelevantSummary
FROM tblPROMsExportSummary AS PES
INNER JOIN TVF_GetRelevantScorecards(#ProcedureID, #AreaID, #StartDate, #EndDate) AS RES ON RES.PROMSID = PES.PROMSID
INNER JOIN tblUploadedScorecards AS UPL ON PES.PROMSID = UPL.PEMSID ) AS T1
INNER JOIN (
SELECT DISTINCT
PES.FKProcedureID ,
PES.PROMSID ,
UPL.PKID AS UploadID ,
MONTH(UPL.ShopDate) AS [Month]
INTO #RelevantSummaryPCT
FROM tblPROMsExportSummary AS PES
INNER JOIN TVF_GetRelevantScorecards(#ProcedureID, 82, #StartDate, #EndDate) AS RES ON RES.PROMSID = PES.PROMSID
INNER JOIN tblUploadedScorecards AS UPL ON PES.PROMSID = UPL.PEMSID ) AS T2
ON T1.PROMSID = T2.PROMSID
To quote directly from the 4guys post
What we are doing is first getting the result set from our derived table (the SELECT statement in the FROM clause). Once we have that resultset, it is as though it was a table in itself. We then perform the SELECT on the derived table, returning our results! You can find another example of using derived tables here on 4GuysFromRolla.com in the article Obtaining Ranked Values from a Table page.
Though my final select looks more like this:
SELECT ISNULL(Volume, 0) AS Volume ,
ISNULL(PCTAverage, 0) AS PCTAverage ,
ShortMonth AS [Month] ,
DisplayOrder
FROM ( SELECT COUNT(DISTINCT ( PROMSID )) AS Volume ,
RS.YearMonth
FROM #RelevantSummary AS RS
GROUP BY YearMonth ) AS RS
INNER JOIN ( SELECT CAST(CAST(COUNT(PROMSID) AS DECIMAL(8, 3))
/ ( SELECT ISNULL(COUNT(DISTINCT RES.Branch), 1)
FROM tblPROMsExportSummary AS PES
INNER JOIN TVF_GetRelevantScorecards(#ProcedureID, #RootReportLevelID, #ReportLevelID, #StartDate,
#EndDate) AS RES ON RES.PROMSID = PES.PROMSID
INNER JOIN tblUploadedScorecards AS UPL ON PES.PROMSID = UPL.PEMSID
WHERE RES.YearMonth = PCT.YearMonth
GROUP BY RES.YearMonth ) AS DECIMAL(8, 3)) AS PCTAverage ,
YearMonth
FROM #RelevantSummaryPCT AS PCT
GROUP BY YearMonth ) AS PCT ON RS.YearMonth = PCT.YearMonth
RIGHT OUTER JOIN ( SELECT *
FROM dbo.TVF_Months(#StartDate, #EndDate) ) AS TVF ON TVF.DisplayOrder = RS.YearMonth
Can someone help me with this query?
SELECT p.OwnerName, SUM(ru.MonthlyRent) AS PotentinalRent, SUM(
(SELECT COUNT(t.ID) * ru.MonthlyRent FROM tblTenant t
WHERE t.UnitID = ru.ID)
) AS ExpectedRent
FROM tblRentalUnit ru
LEFT JOIN tblProperty p ON p.ID = ru.PropertyID
GROUP BY p.OwnerName
I'm having problems with the second sum, it won't let me do it. Evidently SUM won't work on subqueries, but I need to calculate the expected rent (MonthlyRent if there is a tenant assigned to the RentalUnit's id, 0 of they're not). How can I make this work?
SELECT p.OwnerName, SUM(ru.MonthlyRent) AS PotentialRent, SUM(cnt) AS ExpectedRent
FROM tblRentalUnit ru
LEFT JOIN
tblProperty p
ON p.ID = ru.PropertyID
OUTER APPLY
(
SELECT COUNT(t.id) * ru.MonthlyRent AS cnt
FROM tblTenant t
WHERE t.UnitID = ru.ID
) td
GROUP BY p.OwnerName
Here's a test script to check:
WITH tblRentalUnit AS
(
SELECT 1 AS id, 100 AS MonthlyRent, 1 AS PropertyID
UNION ALL
SELECT 2 AS id, 300 AS MonthlyRent, 2 AS PropertyID
),
tblProperty AS
(
SELECT 1 AS id, 'Owner 1' AS OwnerName
UNION ALL
SELECT 2 AS id, 'Owner 2' AS OwnerName
),
tblTenant AS
(
SELECT 1 AS id, 1 AS UnitID
UNION ALL
SELECT 2 AS id, 1 AS UnitID
)
SELECT p.OwnerName, SUM(ru.MonthlyRent) AS PotentialRent, SUM(cnt) AS ExpectedRent
FROM tblRentalUnit ru
LEFT JOIN
tblProperty p
ON p.ID = ru.PropertyID
OUTER APPLY
(
SELECT COUNT(t.id) * ru.MonthlyRent AS cnt
FROM tblTenant t
WHERE t.UnitID = ru.ID
) td
GROUP BY p.OwnerName
What is the meaning of the sum of the unitMonthlyRent times the number of tenants, for some partiicular rental unit (COUNT(t.ID) * ru.MonthlyRent )?
Is it the case that all you are trying to do is see the difference between the total potential rent from all untis versus the expected rent (From only occcupied units) ? If so, then try this
Select p.OwnerName,
Sum(r.MonthlyRent) AS PotentinalRent,
Sum(Case t.Id When Null Then 0
Else r.MonthlyRent End) ExpectedRent
From tblRentalUnit r
Left Join tblTenant t
On t.UnitID = r.ID
left Join tblProperty p
On p.ID = r.PropertyID)
Group By p.OwnerName