Find 10 users with the highest sum of product sales - database

I have two classes, User and Sell. I am trying to compose a request to find 10 people with the largest sum of sales
Task:
Find 10 users
with the highest sum of product sales
find the largest count of sales
select sum_amount_total.*
from (select sum(amount) as total_amount
from
User as u
join Sell as a on u.id = a.seller
group by amount
) as amountSum
join (select sum(amount) as sum_amount
from
Sell
group by
seller
order by
sum_amount desc
) as sum_amount_total on amountSum.total_amount > sum_amount_total.sum_amount limit 2;
create table script
Create table User (id int, name varchar(255));
Truncate table User;
insert into User (id, name) values ('1', 'Joe');
insert into User (id, name) values ('2', 'Henry');
Create table Sell (id int, seller INT, buyer INT, amount FLOAT);
Truncate table Sell;
insert into Sell (id, seller, buyer, amount) values (1, 1, 2, 134444.7);
insert into Sell (id, seller, buyer, amount) values (2, 2, 1, 1241.7);
insert into Sell (id, seller, buyer, amount) values (3, 1, 2, 123.4);
insert into Sell (id, seller, buyer, amount) values (4, 1, 2, 1000000.0);
Problem:
how to simplify the sql script?
I do not understand why my request is not working correctly. Example:
select * from Sell;
Result:
id|seller|buyer|amount
1, 1, 2, 134445
2, 1, 3, 1241.7
3, 2, 1, 123.4
4, 3, 3, 123.4
5, 3, 2, 134445
6, 2, 3, 1241.7
7, 2, 1, 123.4
8, 1, 3, 123.4
9, 1, 3, 10000
10,1, 3, 1000000
my query(1) for finding the largest amount:
sum_amount
134568.10312652588
134568.10312652588
1488.4999542236328
1488.4999542236328
1488.4999542236328
1488.4999542236328
My request does not correctly calculate the largest sum
What needs to be changed for the sql script to work and add a condition to search for the largest count of sales?
Thanks in advance for your answer!

Simplifying your sql script for table User :
insert into User (id, name) values ('1', 'Joe'), ('2', 'Henry');
instead of
insert into User (id, name) values ('1', 'Joe');
insert into User (id, name) values ('2', 'Henry');
The same for table Sell :
insert into Sell (id, seller, buyer, amount) values (1, 1, 2, 134444.7), (2, 2, 1, 1241.7), (3, 1, 2, 123.4), (4, 1, 2, 1000000.0);
Then finding 10 users with the highest sum of product sales :
WITH list AS
(
select seller, sum(amount) as total_amount
from Sell
group by seller
order by total_amount DESC
limit 10
)
select u.*, l.total_amount
from list AS l
inner join user AS u
on u.id = l.seller
Finally finding 10 users with the largest count of product sales :
WITH list AS
(
select seller, coun(*) as total_count
from Sell
group by seller
order by total_count DESC
limit 10
)
select u.*, l.total_count
from list AS l
inner join user AS u
on u.id = l.seller

create table script
Create table User(id int, name varchar(255));
Truncate table Users;
insert into Users (id, name) values ('1', 'Joe');
insert into Users (id, name) values ('2', 'Henry');
insert into Users (id, name) values ('3', 'Liza');
Create table Sell (id int, seller INT, buyer INT, amount FLOAT);
Truncate table Sell;
insert into Sell (id, seller, buyer, amount) values (1, 1, 2, 134444.7);
insert into Sell (id, seller, buyer, amount) values (2, 2, 1, 1241.7);
insert into Sell (id, seller, buyer, amount) values (3, 1, 2, 123.4);
insert into Sell (id, seller, buyer, amount) values (4, 1, 2, 1000000.0);
insert into Sell (id, seller, buyer, amount) values (5, 3, 2, 134445);
insert into Sell (id, seller, buyer, amount) values (6, 2, 3, 1241.7);
insert into Sell (id, seller, buyer, amount) values (7, 2, 1, 123.4);
insert into Sell (id, seller, buyer, amount) values (8, 3, 3, 123.4);
insert into Sell (id, seller, buyer, amount) values (9, 1, 3, 10000);
insert into Sell (id, seller, buyer, amount) values (10,1, 3, 1000000);
query to get count of sales
SELECT name,count(Sell.id) as nsales,sum(amount),rank()
over(order by count(Sell.id) desc)
from Sell
inner join Users
on(seller=Users.id) group by name
limit 10;
name | nsales | sum | rank
-------+--------+-----------+------
Joe | 5 | 2144568.1 | 1
Henry | 3 | 2606.8 | 2
Liza | 2 | 134568.4 | 3
and query to get top of amount
SELECT name,count(Sell.id) as nsales,sum(amount),rank()
over(order by sum(amount) desc)
from Sell
inner join Users
on(seller=Users.id) group by name
limit 10;
name | nsales | sum | rank
-------+--------+-----------+------
Joe | 5 | 2144568.1 | 1
Liza | 2 | 134568.4 | 2
Henry | 3 | 2606.8 | 3
same result without ranking
SELECT name,count(Sell.id) as nsales,sum(amount) amount_sum
from Sell inner join Users on(seller=Users.id)
group by name
order by amount_sum desc
limit 10;
name | nsales | amount_sum
-------+--------+------------
Joe | 5 | 2144568.1
Liza | 2 | 134568.4
Henry | 3 | 2606.8
SELECT name,count(Sell.id) as nsales,sum(amount) amount_sum
from Sell inner join Users on(seller=Users.id)
group by name
order by nsales desc
limit 10;
name | nsales | amount_sum
-------+--------+------------
Joe | 5 | 2144568.1
Henry | 3 | 2606.8
Liza | 2 | 134568.4

Related

T-SQL average page count for each employee

I have 2 different tables and I would like an average page count per hour for each employee. I am new to subqueries so I'm still trying to wrap my head around them. This is what I have so far but I need the average page count for each employee but I am getting the
average total.
SELECT
Employee,
((SELECT SUM(Pagecount) FROM Table2) /
(SELECT SUM(Duration) FROM Table1))
FROM Table1;
You should not need a subquery here, rather you would want to JOIN the tables together.
DECLARE #Table1 TABLE (PrepDate DATE, PickupNumber INT, BoxNumber INT, JobType INT, Duration DECIMAL(5, 2), Employee VARCHAR(100), BoxStatus VARCHAR(5));
DECLARE #Table2 TABLE (ScanDate DATE, PickupNumber INT, BoxNumber INT, PageCount INT);
INSERT #Table1 (PrepDate, PickupNumber, BoxNumber, JobType, Duration, Employee, BoxStatus)
VALUES ('20220707', 123, 8, 0, 3.75, 'Jdoe', 'I'),
('20220808', 456, 9, 0, 5.25, 'Msmith', 'C');
INSERT #Table2 (ScanDate, PickupNumber, BoxNumber, PageCount)
VALUES ('20220807', 123, 8, 525),
('20220823', 456, 9, 785);
SELECT t1.Employee, (t2.PageCount / t1.Duration) AS AvgPageCount
FROM #Table1 t1
INNER JOIN #Table2 t2 ON t2.PickupNumber = t1.PickupNumber
AND t2.BoxNumber = t1.BoxNumber;
This will produce:
Employee | AvgPageCount
-------------+-----------------
Jdoe | 140.000000
Msmith | 149.523809

4 table join with count query

I'm using a SQL Server database with 4 tables like this:
Product table: Product_id is the primary key of the table:
| Product_id | Product_name | Description |
Project table: Project_id is the primary key of the table, Product_id is the foreign key to the Product table.
| Project_id | Project_name | Project_start_date | Product_id |
Participant table: Participant_id is the primary key of the table, Project_id is the foreign key to the Project table.
| Participant_id | Participant_name | Participant_email | Project_ID |
Response table: Response_id is the primary key of the table, participant_id is a foreign key to the Participant table.
My question is is it possible I can join all 4 tables together and list product name, project name, participant email and get the count of participants for each project and all response for each project?
Edit:
I feel it's better I put my code here. This is what I've tried, so please do not tell me use JOIN only...
This is the code I got total participant:
SELECT
projects.Project_ID,
count(*) total_Participants,
projects.Project_Name,
projects.Product_ID,
products.Product_Name
FROM
Project projects
INNER JOIN Participant participant on
projects.Project_ID = participant.Project_ID
INNER JOIN Products products ON
products.Product_ID = projects.Product_ID
group by
projects.Project_ID,
projects.Project_Name,
projects.Product_ID,
products.Product_Name,
projects.Project_ID
ORDER BY
projects.Project_ID DESC
And this is the code I got total response:
SELECT
projects.Project_ID,
count(*) total_Participants,
projects.Project_Name,
projects.Product_ID,
products.Product_Name
FROM
Project projects
INNER JOIN Participant participant on
projects.Project_ID = participant.Project_ID
INNER JOIN Products products ON
products.Product_ID = projects.Product_ID
INNER JOIN Response Response ON
Response.Participant_ID = participant.Participant_ID
group by
projects.Project_ID,
projects.Project_Name,
projects.Product_ID,
products.Product_Name,
projects.Project_ID
ORDER BY
projects.Project_ID DESC
Is this a way I can use one query statement to get participant_email, total participants and total response all together?
Without an example of your expected result, this is the best I could come up with.
Some sample data:
declare #product table
(
product_id int,
product_name nvarchar(20)
);
insert into #product (product_id, product_name) values
(1, 'Product ABC'),
(2, 'Product DEF'),
(3, 'Product GHI');
declare #project table
(
project_id int,
project_name nvarchar(20),
product_id int
);
insert into #project (project_id, project_name, product_id) values
(1, 'Project 001', 1),
(2, 'Project 002', 1),
(3, 'Project 003', 2),
(4, 'Project 004', 3);
declare #participant table
(
participant_id int,
participant_name nvarchar(20),
participant_email nvarchar(20),
project_id int
);
insert into #participant (participant_id, participant_name, participant_email, project_id) values
(1, 'Andy', 'andy#host.org', 1),
(2, 'Beatrice', 'beatrice#host.org', 1),
(3, 'Charles', 'charles#host.org', 2),
(4, 'Charles', 'charles#host.org', 4),
(5, 'David', 'david#host.org', 3),
(6, 'Eve', 'eve#host.org', 2);
declare #response table
(
response_id int,
response_content nvarchar(100),
participant_id int
);
insert into #response (response_id, response_content, participant_id) values
(1, 'please', 1),
(2, 'provide', 2),
(3, 'sample', 2),
(4, 'data', 3),
(5, 'next', 5),
(6, 'time', 4),
(7, 'thank', 6),
(8, 'you', 6),
(9, '>.<', 6);
Possible solution, using Common Table Expressions (CTE's) to isolate the count subqueries:
with cte_part as
(
select proj.project_id, count(1) as 'participant_count'
from #project proj
join #participant part on part.project_id = proj.project_id
group by proj.project_id
),
cte_resp as
(
select proj.project_id, count(1) as 'response_count'
from #project proj
join #participant part on part.project_id = proj.project_id
join #response resp on resp.participant_id = part.participant_id
group by proj.project_id
)
select prod.product_name,
proj.project_name,
part.participant_email,
cp.participant_count,
cr.response_count
from #product prod
join #project proj on proj.product_id = prod.product_id
join #participant part on part.project_id = proj.project_id
join cte_part cp on cp.project_id = proj.project_id
join cte_resp cr on cr.project_id = proj.project_id
order by prod.product_name;
This gives me:
product_name project_name participant_email participant_count response_count
-------------------- -------------------- -------------------- ----------------- --------------
Product ABC Project 001 andy#host.org 2 3
Product ABC Project 001 beatrice#host.org 2 3
Product ABC Project 002 charles#host.org 2 4
Product ABC Project 002 eve#host.org 2 4
Product DEF Project 003 david#host.org 1 1
Product GHI Project 004 charles#host.org 1 1

Filter Table Before Applying Right Join ON 3RD TABLE

Using MSSQL: Just for clarification
Customer Table
CustomerNumber Name
===================
1 David
2 Thomas
3 Mangold
4 Issac
------------------------------------------------------------
CustomerAddress Table
CustomerNumber State EffectiveDate
==================================
1 AL 01/01/2017
1 VA 06/01/2017
1 GA 02/01/2018
1 FL 10/01/2018
2 TX 01/01/2017
3 MA
4 IL 04/01/2015
SalesOrder Table
CUSTOMER ORDERNo OrderDate
========================
1 1000 03/01/2017
2 1001 10/10/2017
1 1002 11/01/2017
3 1003 12/01/2017
4 1004 01/01/2018
1 1005 02/01/2018
1 1006 01/01/2019
I need to fetch all the orders with the customer detail and the customer address on the order date.
SELECT T1.ORDERNo, T1.ORDERDATE, T1.CUSTOMER, T2.NAME, T3.STATE
FROM SALESORDER T1, CUSTOMER T2, CUSTOMERADDRESS T3
RIGHT JOIN(
SELECT CUSTOMER, MAX(EFFECTIVEDATE) FROM CUSTOMERADDRESS
--WHERE EFFECTIVEDATE <= T1.ORDERDATE
GROUP BY CUSTOMER)T4
ON T3.CUSTOMER = T4.CUSTOMER AND T3.EFFECTIVEDATE=T4.EFFECTIVEDATE
WHERE T1.CUSTOMER = T2.CUSTOMERNUMBER
AND T1.CUSTOMER = T3.CUSTOMERNUMBER
Want to see how to do compare in the join where i compare first table to the 3rd table in the join. see the commented code --WHERE EFFECTIVEDATE <= T1.ORDERDATE
If I remove the commented code, the table in the join cannot reference a table outside.
The expected output is:
CUSTOMER ORDERNo OrderDate CustomerName State
=============================================
1 1000 03/01/2017 David AL
2 1001 10/10/2017 Thomas TX
1 1002 11/01/2017 David VA
3 1003 12/01/2017 Mangold MA
4 1004 01/01/2018 Issac IL
1 1005 02/01/2018 David GA
1 1006 01/01/2019 David FL
The tables in sql fiddle http://sqlfiddle.com/#!18/9eecb:
CREATE TABLE Customer
('CustomerNumber' int, 'CustomerName' varchar(30))
;
INSERT INTO Customer
('CustomerNumber', 'CustomerName')
VALUES
(1, 'David'),
(2, 'Thomas'),
(3, 'Mangold'),
(4, 'Issac')
;
CREATE TABLE CustomerAddress
('CustomerNumber' int, 'State' varchar(2), 'EffectiveDate' date)
;
INSERT INTO CustomerAddress
('CustomerNumber', 'State', 'EffectiveDate')
VALUES
(1, 'AL', 01/01/2017),
(1, 'VA', 06/01/2017),
(1, 'GA', 02/01/2018),
(1, 'FL', 10/01/2018),
(2, 'TX', 01/01/2017),
(3, 'MA',),
(4, 'IL', 04/01/2015)
;
CREATE TABLE SalesOrder
('CUSTOMER' int, 'ORDERNO' int, 'OrderDate' Date)
;
INSERT INTO SalesOrder
('CUSTOMER', 'ORDERNO', 'OrderDate')
VALUES
(1, 1000, 03/01/2017),
(2, 1001, 10/10/2017),
(1, 1002, 11/01/2017),
(3, 1003, 12/01/2017),
(4, 1004, 01/01/2018),
(1, 1005, 02/01/2018),
(1, 1006, 01/01/2019)
;
CREATE TABLE CustomerAddress
(`CustomerNumber` int, 'State' varchar(2), `EffectiveDate` date)
;
INSERT INTO CustomerAddress
(`CustomerNumber`, `State`, 'EffectiveDate')
VALUES
(1, 'AL', 01/01/2017),
(1, 'VA', 06/01/2017),
(1, 'GA', 02/01/2018),
(1, 'FL', 10/01/2018),
(2, 'TX', 01/01/2017),
(3, 'MA',),
(4, 'IL', 04/01/2015)
;
CREATE TABLE SalesOrder
(`CUSTOMER` int, 'ORDERNO' int, `OrderDate` Date)
;
INSERT INTO SalesOrder
(`CUSTOMER `, `ORDERNO`, 'OrderDate')
VALUES
(1, 1000, 03/01/2017),
(2, 1001, 10/10/2017),
(1, 1002, 11/01/2017),
(3, 1003, 12/01/2017),
(4, 1004, 01/01/2018),
(1, 1005, 02/01/2018),
(1, 1006, 01/01/2019)
;
'sql server version'
CREATE TABLE Customer
(CustomerNumber int, CustomerName varchar(30))
;
INSERT INTO Customer
(CustomerNumber, CustomerName)
VALUES
(1, 'David'),
(2, 'Thomas'),
(3, 'Mangold'),
(4, 'Issac');
;
CREATE TABLE CustomerAddress
(CustomerNumber int, State varchar(2), EffectiveDate date)
;
INSERT INTO CustomerAddress
(CustomerNumber, State, EffectiveDate)
VALUES
(1, 'AL', '01/01/2017'),
(1, 'VA', '06/01/2017'),
(1, 'GA', '02/01/2018'),
(1, 'FL', '10/01/2018'),
(2, 'TX', '01/01/2017'),
(4, 'IL', '04/01/2015')
;
INSERT INTO CustomerAddress
(CustomerNumber, State)
VALUES
(3, 'MA' )
;
CREATE TABLE SalesOrder
(CUSTOMER int, ORDERNO int, OrderDate Date)
;
INSERT INTO SalesOrder
(CUSTOMER, ORDERNO, OrderDate)
VALUES
(1, 1000, '03/01/2017'),
(2, 1001, '10/10/2017'),
(1, 1002, '11/01/2017'),
(3, 1003, '12/01/2017'),
(4, 1004, '01/01/2018'),
(1, 1005, '02/01/2018'),
(1, 1006, '01/01/2019')
;
The problem: Need to Pick all the Sales Orders and their customer Name, and the Customer Address. The important and tricky part is the customer address changes based on the date of the sales order.
--MODIFIED VERSION OF THE INCOMPLETE QUERY
SELECT T1.ORDERNo, T1.ORDERDATE, T1.CUSTOMER, T2.CustomerName, T3.STATE
FROM CUSTOMER T2, SALESORDER T1 INNER JOIN CUSTOMERADDRESS T3 ON T1.CUSTOMER = T3.CUSTOMERNUMBER
RIGHT JOIN(
SELECT CustomerNumber, MAX(EFFECTIVEDATE) as EffectiveDate4 FROM CUSTOMERADDRESS
--WHERE EFFECTIVEDATE < T1.ORDERDATE
GROUP BY CustomerNumber
--HAVING EFFECTIVEDATE < T1.ORDERDATE
) T4
ON T3.CustomerNumber = T4.CustomerNumber AND T3.EFFECTIVEDATE=T4.EffectiveDate4
WHERE T1.CUSTOMER = T2.CUSTOMERNUMBER
OUTER APPLY should solve your problem. based on your needs you can change your query.
SELECT T1.ORDERNo, T1.ORDERDATE, T1.CUSTOMER, T2.NAME, T3.STATE
FROM SALESORDER T1, CUSTOMER T2, CUSTOMERADDRESS T3
OUTER APPLY(
SELECT CUSTOMER, MAX(EFFECTIVEDATE) FROM CUSTOMERADDRESS
WHERE EFFECTIVEDATE <= T1.ORDERDATE
AND T3.CUSTOMER = CUSTOMER )T4
WHERE T1.CUSTOMER = T2.CUSTOMERNUMBER
AND T1.CUSTOMER = T3.CUSTOMERNUMBER
AND T3.EFFECTIVEDATE = T4.EFFECTIVEDATE

How can I recursively calculate a value

I have this table.
Bundles
id | parent_id | quantity
1 | 0 | 1
2 | 1 | 4
3 | 2 | 5
I want to get the total quantity of a bundle with id 3, which is 1 * 4 * 5 = 20 items
Can this be done with a single query?
Here's a solution using CTE:
Setup:
CREATE TABLE Table1
(id int, parent_id int, quantity int)
;
INSERT INTO Table1
(id, parent_id, quantity)
VALUES
(1, 0, 1),
(2, 1, 4),
(3, 2, 5),
(4, 0, 7),
(5, 4, 10)
;
CTE to return total of id=3 and it's parent items:
;WITH myCTE AS
(
SELECT id, parent_id, quantity
FROM Table1
WHERE id = 3
UNION ALL
SELECT T.id, T.parent_id, T.quantity
FROM Table1 T
JOIN myCTE C ON T.id = C.parent_id
)
SELECT EXP(sum(log(quantity)))
FROM myCTE
Demo SQL Fiddle
Multiplication method for values in a column, SELECT EXP(sum(log(quantity))), taken from here.

COUNT number of rows in a GROUP on higher aggregate level

I am trying to find out how many rows of a certain item exist in the table, e.g. in the following example for itemID 1 I need the result 5 (not 3, which is what I currently get). I am tempted to add TransactionID into the PARTITION BY clause, but that results in Msg 8120 since the query does not GROUP by TransactionID. Well, if it did then getting that count would be easy, but I do not want to group on Transaction Level. What can I do to get that ItemCount right? It must be so easy but I am banging my head.
DECLARE #t TABLE (TransactionID INT PRIMARY KEY IDENTITY, CustomerID INT, ItemID INT);
INSERT INTO #t (CustomerID, ItemID)
VALUES
(1, 1),
(2, 1),
(3, 1),
(4, 2),
(1, 1),
(2, 2),
(3, 3),
(4, 4),
(1, 1);
SELECT
CustomerID,
ItemID,
Rows = COUNT(*),
ItemRowCount = COUNT(*) OVER (PARTITION BY ItemID)
FROM
#t
GROUP BY
CustomerID,
ItemID
ORDER BY
ItemID,
CustomerID;
EDIT: I was overaggregating, I guess. Sebastian Meine got me on the track and his answer is right so I accepted it. However, this subquery works for my:
SELECT
CustomerID,
ItemID,
Rows = COUNT(*),
ItemRowCount = (SELECT COUNT(*) FROM #t x WHERE t.ItemID = x.ItemID)
FROM
#t t
GROUP BY
CustomerID,
ItemID
ORDER BY
ItemID,
CustomerID;
You need to pull your outer group count out of the actual group by query. The easiest way to do that is like this:
SQL Fiddle
MS SQL Server 2008 Schema Setup:
CREATE TABLE dbo.tbl (TransactionID INT PRIMARY KEY IDENTITY, CustomerID INT, ItemID INT);
INSERT INTO dbo.tbl (CustomerID, ItemID)
VALUES
(1, 1),
(2, 1),
(3, 1),
(4, 2),
(1, 1),
(2, 2),
(3, 3),
(4, 4),
(1, 1);
Query 1:
SELECT *,SUM(Rows)OVER(PARTITION BY ItemId) ItemCnt
FROM(
SELECT
CustomerID,
ItemID,
Rows = COUNT(*)
FROM
dbo.tbl
GROUP BY
CustomerID,
ItemID
)X
ORDER BY
ItemID,
CustomerID
Results:
| CUSTOMERID | ITEMID | ROWS | ITEMCNT |
----------------------------------------
| 1 | 1 | 3 | 5 |
| 2 | 1 | 1 | 5 |
| 3 | 1 | 1 | 5 |
| 2 | 2 | 1 | 2 |
| 4 | 2 | 1 | 2 |
| 3 | 3 | 1 | 1 |
| 4 | 4 | 1 | 1 |
Notice that I add the inner counts together instead of recounting from scratch.
You can use simple count and group by:
SELECT
ItemID,
ItemRowCount = COUNT(1)
FROM
#t
GROUP BY
ItemID
ORDER BY
ItemID
or if you need attach total rows count and item row count to every row:
SELECT
CustomerID,
ItemID,
Rows = COUNT(1) over (),
ItemRowCount = COUNT(1) OVER (PARTITION BY ItemID)
FROM
#t
ORDER BY
ItemID,
CustomerID;
To find out how many rows of a certain item exist in the table, we may not need CustomerId. Use following query -
DECLARE #t TABLE (TransactionID INT PRIMARY KEY IDENTITY, CustomerID INT, ItemID INT);
INSERT INTO #t (CustomerID, ItemID)
VALUES
(1, 1),
(2, 1),
(3, 1),
(4, 2),
(1, 1),
(2, 2),
(3, 3),
(4, 4),
(1, 1);
;WITH cte AS(
SELECT itemId, ROW_NUMBER() OVER (PARTITION BY itemId ORDER BY itemId DESC) AS row_cnt FROM #t
)
SELECT itemId, MAX(row_cnt) row_count FROM cte GROUP BY itemId
It will return -
itemId row_count
1 5
2 2
3 1
4 1
And if is case you need customerId, the use -
;WITH cte AS(
SELECT customerId, itemId, ROW_NUMBER() OVER (PARTITION BY itemId ORDER BY itemId DESC) AS row_cnt FROM #t
)
SELECT customerId, itemId, MAX(row_cnt) item_count FROM cte GROUP BY CustomerID, itemId
It will return -
customerId itemId item_count
1 1 5
2 1 2
3 1 3
2 2 1
4 2 2
3 3 1
4 4 1
You can use a CTE or join to a sub-table (like this)
SELECT
tbl.CustomerID,
tbl.ItemID,
Rows = COUNT(*),
ItemRowCount
FROM tbl
JOIN (SELECT ItemID, Count(*) as ItemRowCount
FROM tbl
GROUP BY ItemID) t ON tbl.ItemID = t.ItemID
GROUP BY
tbl.CustomerID,
tbl.ItemID,
ItemRowCount
ORDER BY
tbl.ItemID,
CustomerID;
or this
SELECT
tbl.CustomerID,
tbl.ItemID,
Rows = COUNT(*),
MAX(ItemRowCount)
FROM tbl
JOIN (SELECT ItemID, Count(*) as ItemRowCount
FROM tbl
GROUP BY ItemID) t ON tbl.ItemID = t.ItemID
GROUP BY
tbl.CustomerID,
tbl.ItemID
ORDER BY
tbl.ItemID,
CustomerID;

Resources