sql - salesmen by territory query - combine multiple statements with WITH clause
-
27-06-2021 - |
Question
We have a territory/salesman relationship where: each Territory (TERR) may have multiple salesman (SALM), but each salesman can have only one territory.
Example:
Territory Salesman Sales$ Period
1 100 999 1
1 100 999 2
1 200 999 1
1 200 999 2
2 300 999 1
2 300 999 2
3 400 999 1
3 400 999 2
I would like to build a summary table, preferably using a single SQL statement that -
- shows territory,
- number of salesmen for this territory (** CLARIFICATION: ** that is total unique salesmen codes that made sales in this territory) and
- list the salesmen numbers in the same file.
example:
Territory # of Salesmen Salesman
--------- ------------- --------
1 2 100
1 2 200
2 1 300
3 1 400
SQL:
// First I get a list of territories and number of salesman in each territory
With tmpFile as (Select TERR, SALM, count(*)
FROM FILE
GROUP BY TERR, SALM
ORDER BY TERR, SALM
)
SELECT tmpFile.TERR, count(*) FROM tmpFile GROUP BY
tmpFile.TERR ORDER BY tmpFile.TERR
// Next step is to get a list of all salesmen in a territory
Select TERR, SALM
FROM FILE
GROUP BY TERR, SALM
ORDER BY TERR, SALM
)
// Final step would be to combine the above two steps. I would like to combine all three steps into a single statement if possible. Is there more effective way to do this. I am using IBM db/2 SQL.
Solution
While I would like to use the OLAP version of the statement, my version of DB2 (V6R1) doesn't support the COUNT()
function in that context (boohoo). That said, here's a version that does work, and should work on any other RDBMS (I think):
SELECT DISTINCT terr, salm, salesmen
FROM File -- I really hope that's not your file name - it's a reserved word
JOIN (SELECT terr territory, COUNT(DISTINCT salm) salesmen
FROM File
GROUP BY terr) Salesmen_Per_Territory
ON territory = terr
Please note the DISTINCT
inside COUNT()
, as this is what is keeping the salesmen from being counted for each period.
OTHER TIPS
Why not do it in single query?
SELECT Territory, SalesMan, COUNT(*) as [No. of Salesman]
FROM tableName
GROUP BY Territory, SalesMan
Are they on different table? eg, TERR
and SALM
?
SELECT a.Territory, b.SalesMan, Count(b.Territory) as [No. of Salesman]
FROM Terr a
INNER JOIN SALM b
on a.Territory = b.Territory
GROUP BY a.Territory, b.SalesMan
I'd say you are on the right track using a common table expression [aka. WITH clause], but it can easily and efficiently be done in one statement.
WITH t as
(SELECT terr, count(distinct salm) as slspeople
FROM yourfile
WHERE salesamt > 0
GROUP BY terr
)
SELECT DISTINCT s.terr, t.slspeople, s.salm
FROM yourfile as s
JOIN t using (terr)
WHERE salesamt > 0
ORDER BY s.terr, s.salm
The using (terr)
clause is a shorthand for on s.terr = t.terr
, where the matching columns must have the same name in both tables.
I added the WHERE salesamt > 0
only because one of your clarification requirements was to only list salespeople who had sales. If this is not applicable take this out, of course.
It may be a good idea to take the various answers provided, and analyze them with Visual Explain. This is a valuable tool where you can try different variations, and see what performs better. I use this on IBM i, but I believe it exists on the other two platforms as well.