How do I use COUNT function on another aggregate function in SQL? - sql

I would like to count the aggregate function, for eg:
SELECT customer_id, SUM(amount)
FROM payment
GROUP BY customer_id
HAVING SUM(amount)>100;
So, how do I use COUNT() on SUM() to count the filtered SUM()?

You wrap it in an outer query.
select count(*) from (
SELECT customer_id, SUM(amount)
FROM payment
GROUP BY customer_id
HAVING SUM(amount)>100
) big_spenders

If you want to count the number of customers for each amount that you get from your query, you need a 2nd level of aggregation:
SELECT amount, COUNT(*) counter
FROM (
SELECT customer_id, SUM(amount) amount
FROM payment
GROUP BY customer_id
HAVING SUM(amount)>100
) t
GROUP BY amount;
Or, with COUNT() window function:
SELECT DISTINCT SUM(amount) amount,
COUNT(*) OVER (PARTITION BY SUM(amount)) counter
FROM payment
GROUP BY customer_id
HAVING SUM(amount)>100;
See a simplified demo.

Related

Grouping in SQL using CASE Statements

Hello I am trying to group multiple customer orders into buckets in SQL, the output should look something like it does below. Do I have to use a case statement to group them?
Table1 looks like:
CustomerID
Order_date
1
somedate
2
somedate
3
somedate
2
somedate
Edit: # of customers meaning if CustomerID 2 had 2 orders he/she would be of the in the bucket of #of orders of 2.
Output should be something like this?
# of Customers
# of Orders
2
1
1
2
My code so far is:
select count(*) CustomerID
FROM Table1
GROUP BY CustomerID;
Use a double aggregation:
SELECT COUNT(*) AS num_customers, cnt AS num_orders
FROM
(
SELECT CustomerID, COUNT(*) AS cnt
FROM Table1
GROUP BY CustomerID
) t
GROUP BY cnt;
The inner subquery finds the number of orders for each customer. The outer query then aggregates by number of orders and finds out the number of customers having each number of orders.
If you want to sort your tables and your users depending on the number of orders they made, this query should work:
SELECT CustomerID, COUNT(CustomerID) as NbOrder
FROM Table1
GROUP BY(NbOrder)
I believe what you want to do is get the count of orders by customer, first, via aggregation. Then get the count of customers by order count from that query.
SELECT count(*) as count_of_customers, count_of_orders
FROM
(
SELECT customerid, count(*) as count_of_orders
FROM your_table
GROUP BY customerid
) sub
GROUP BY count_of_orders
ORDER BY count_of_orders

Count Function after query in postgres sql

I have written some query and I wanted to know the number of rows or total rows count. Is there a "count" function that can be applied on top of the query?
My query is like:
select customer_id, sum(amount)
from payment
group by customer_id having sum(amount)>100;
You could use count() as a window function, like in
SELECT *,
count(*) OVER () AS total_count
FROM (SELECT customer_id,
sum(amount)
FROM payment
GROUP BY customer_id HAVING sum(amount)>100) AS q;
That will return the total count in an additional column.
You can use a subquery or CTE:
select count(*)
from (select customer_id, sum(amount)
from payment
group by customer_id
having sum(amount)>100
) c;

Combine two SQL statements with sum

Two statements need to combine.
select INVOICEAMOUNT, itemid
from MTS_NONPAYMENT
select SUM(AMOUNT) AS SUM, ITEMID
from CUS_GLACCOUNT
Common column itemid. Each time I try and join, it fails. What am I doing wrong?
Fundamentally, you appear to be missing group by. I suspect the following does what you want:
select itemid, sum(invoiceamount) as invoiceamount, sum(sum) as sum
from ((select itemid, sum(INVOICEAMOUNT) as invoiceamount, 0 as sum
from MTS_NONPAYMENT
group by itemid
) union all
(select itemid, 0, SUM(AMOUNT)
from CUS_GLACCOUNT
group by itemid
)
) x
group by itemid;
To get unequal values, use:
having sum(invoiceamount) <> sum(sum)
at the end of the query.

The SUM of an aggregate COUNT function

I want to create a query to calculate the percentage sales of the overall policies in my database.
The policies are split under two separate headings
UL
NL
The code i want should display
product name
number of policies sold
policies sold per product as a percentage of the overall number of policies sold.
I have made a few attempts at scripting this code (please see below) but cannot get them to run correctly.
Syntax 1:
SELECT b.PRODUCT_NAME, b.POLICIES_SOLD, 100.00*(b.POLICIES_SOLD/SUM(b.POLICIES_SOLD)) AS'PERC_SALES'
FROM
(
SELECT a.PRODUCT_NAME, COUNT(a.PRODUCT_NAME) AS
'POLICIES_SOLD'
FROM
(SELECT PRODUCT_NAME FROM [ATLANTIS\jjudge].
[ALL_POLICIES_201706_NL]
UNION ALL
SELECT PRODUCT_NAME FROM [ATLANTIS\jjudge].
[ALL_POLICIES_201706_UL])a GROUP BY PRODUCT_NAME)b ;
Syntax 2:
SELECT a.PRODUCT_NAME, a.[POLICIES SOLD], 100.00*(a.[POLICIES SOLD]/SUM(a.[POLICIES SOLD]))
FROM
(SELECT PRODUCT_NAME, COUNT(*) AS 'POLICIES SOLD'FROM
[ATLANTIS\jjudge].[ALL_POLICIES_201706_NL] GROUP BY PRODUCT_NAME
UNION ALL
SELECT PRODUCT_NAME, COUNT(*) AS 'POLICIES SOLD' FROM
[ATLANTIS\jjudge].[ALL_POLICIES_201706_UL] GROUP BY
PRODUCT_NAME)a ;
Syntax 3:
SELECT b.PRODUCT_NAME, COUNT(b.PRODUCT_NAME) AS
'POLICIES_SOLD', 100.00*
(COUNT(b.PRODUCT_NAME)/SUM(SELECT(PRODUCT_NAME))
FROM
(SELECT COUNT(*) AS 'POLICY_COUNT' FROM [ATLANTIS\jjudge].[ALL_POLICIES_201706_NL]
UNION ALL
SELECT COUNT(*) AS 'POLICY_COUNT' FROM [ATLANTIS\jjudge].[ALL_POLICIES_201706_UL])a)) AS 'PERC_SALES'
FROM
(SELECT PRODUCT_NAME FROM [ATLANTIS\jjudge].
[ALL_POLICIES_201706_NL]
UNION ALL
SELECT PRODUCT_NAME FROM [ATLANTIS\jjudge].
[ALL_POLICIES_201706_UL])b GROUP BY PRODUCT_NAME;
I think you want a Window Function. Modify your Syntax 1 first line as:
SELECT
b.PRODUCT_NAME,
b.POLICIES_SOLD,
100.00*b.POLICIES_SOLD/SUM(b.POLICIES_SOLD) OVER () AS 'PERC_SALES'
You can do this using a single aggregation query with window functions:
SELECT p.PRODUCT_NAME, COUNT(*) AS POLICIES_SOLD,
COUNT(*) * 100.0 / SUM(COUNT(*)) OVER () as PERC_SALES
FROM ((SELECT PRODUCT_NAME
FROM [ATLANTIS\jjudge].[ALL_POLICIES_201706_NL]
) UNION ALL
(SELECT PRODUCT_NAME
FROM [ATLANTIS\jjudge].[ALL_POLICIES_201706_UL]
)
) p
GROUP BY PRODUCT_NAME;

prepare the monthly sales report for the customer who has the maximum sales, for the below table

prepare the monthly sales report for the customer who has the maximum sales, for the below table
This is an example of how you can retrieve in 'one' query:
the id of the customer who has the maximum sales
the sales summary of this customer
First the query that brings the customer_id and the corresponding summary of sales is like:
select customer_id, sum(sales) as sumsales from mytable group by customer_id;
To this query, a rank has to be added to the descending order of Sales summaries. This will allow to select a single record according to its rank later. So, a wrap is necessary:
select customer_id, sumsales, rank() over (order by sumsales desc) as rnk from
(select customer_id, sum(sales) as sumsales from mytable group by customer_id);
Now that the ranked entries are available, the first ranked record has to be selected:
select customer_id, sumsales from
(select customer_id, sumsales, rank() over (order by sumsales desc) as rnk from
(select customer_id, sum(sales) as sumsales from mytable group by customer_id)
)
where rnk=1;
However, this may not be the most effective way to achieve this.
EDIT:
In order to avoid a wrapping layer, just to add the rank, it is possible to add the rank foeld to the first internal query:
select customer_id, sum(sales) as sumsales, rank() over (order by sum(sales) desc) as rnk
from mytable group by customer_id;
And then, a single wrapping query is needed to select the first ranked record as:
select customer_id, sumsales from (
select customer_id, sum(sales) as sumsales, rank() over (order by sum(sales) desc) as rnk
from mytable group by customer_id
)
where rnk=1;
Reference to other similar relevant answers here.