Reputation: 135
I have calculated the TOP 10
running total of a table and now want to get this in percentage for a pareto diagram, I have the following code:
WITH
CTE as
(
SELECT
[nWordNr] as W,
[nBitNr] as B,
SUM([tmTotals]) as total,
COUNT(*) as Amount
FROM Messages_History
GROUP BY nWordNr, nBitNr
),
totAlarms as
(
select
count([nWordNr]) as cnt
FROM Messages_History
)
SELECT TOP 10 *,
SUM(total) OVER (ORDER BY total desc) * 1.0 / totAlarms.cnt as Running
FROM CTE
ORDER BY total desc
When I want to use totAlarms.cnt
to calculate the running percentage I get the following error:
The multi-part identifier "totAlarms.cnt" could not be bound.
How can I use totAlarms.cnt
to calculate the running percentage.
Upvotes: 2
Views: 954
Reputation: 97948
CTEs aren't automatically included in the attached query, you have to mention them in a FROM
or JOIN
clause.
Your current query is of the form:
WITH
CTE AS ( ... ),
totAlarms AS ( ... )
SELECT ...
FROM CTE
ORDER BY ...
So only CTE
is visible in the SELECT
clause. totAlarms
is defined but never used - like creating a VIEW
but not writing any queries that reference it.
Since your two CTEs are independent, you need to CROSS JOIN
them, giving this form:
WITH
CTE AS ( ... ),
totAlarms AS ( ... )
SELECT ...
FROM CTE
CROSS JOIN totAlarms
ORDER BY ...
Or using the ,
operator, which is effectively a cross join:
WITH
CTE AS ( ... ),
totAlarms AS ( ... )
SELECT ...
FROM CTE, totAlarms
ORDER BY ...
Upvotes: 2
Reputation: 463
WITH
CTE as
(
SELECT
[nWordNr] as W,
[nBitNr] as B,
SUM([tmTotals]) as total,
COUNT(*) as Amount
FROM Messages_History
GROUP BY nWordNr, nBitNr
),
totAlarms as
(
select
count([nWordNr]) as cnt
FROM Messages_History
)
SELECT TOP 10 *,
SUM(total) OVER (ORDER BY total desc) * 1.0 / totAlarms.cnt as Running
FROM CTE,totAlarms
ORDER BY total desc
With the help of cross join you can achieve it. The multi-part identifier "totAlarms.cnt" could not be bound. This error was showing becoz you are not using totAlarms (CTE table) in join or from.
Upvotes: 3
Reputation: 5893
Instead of writing sub CTE's try to create variable and store value and use like below
declare @nWordNr int
select @nWordNr=count(nWordNr) FROM Messages_History
;WITH
CTE as
(
SELECT
[nWordNr] as W,
[nBitNr] as B,
SUM([tmTotals]) as total,
COUNT(*) as Amount
FROM Messages_History
GROUP BY nWordNr, nBitNr
)--,
--totAlarms as
--(
--select
--count([nWordNr]) as cnt
--FROM Messages_History
--)
SELECT TOP 10 *,
SUM(total) OVER (ORDER BY total desc) * 1.0 / @nWordNr as Running
FROM CTE
ORDER BY total desc
Upvotes: 1
Reputation: 15150
Since the count is just a single value, I'd capture it in a scalar variable:
DECLARE @totAlarms_cnt INT = (
SELECT COUNT([nWordNr]) as cnt
FROM Messages_History
)
;
WITH
CTE as
(
SELECT
[nWordNr] as W,
[nBitNr] as B,
SUM([tmTotals]) as total,
COUNT(*) as Amount
FROM Messages_History
GROUP BY nWordNr, nBitNr
)
SELECT TOP 10 *,
SUM(total) OVER (ORDER BY total desc) * 1.0 / @totAlarms_cnt as Running
FROM CTE
ORDER BY total desc
Upvotes: 1