Maximum count - PostgreSQL - sql

I'm looking to pull the max(count(*)) of something from a table.
Effectively what i'm trying to do is pull out a customers favourite brand. So they buy 300 bars of soap a year but I'd like to know which their favourite is. So the max(count(brand_id) basically.
I was thinking of doing it like this:
SELECT
transaction.customer_id,
max(occ)
FROM
( SELECT
transaction.customer_id,
count(transaction.brand_id) as occ,
FROM
transaction
GROUP BY
transaction.customer_id,
) AS foo
GROUP BY
transaction.customer_id
Thanks in advance

you can do it like this:
with cte as (
select customer_id, brand_id, count(*) as cnt
from test1
group by customer_id, brand_id
)
select distinct on (customer_id)
customer_id, brand_id, cnt
from cte
order by customer_id, cnt desc
Keep in mind, that if there more than one brand with equal count for some customer, you'll end up with one arbitrary record. If you want to get all records, use dense_rank() function:
with cte1 as (
select customer_id, brand_id, count(*) as cnt
from test1
group by customer_id, brand_id
), cte2 as (
select
customer_id, brand_id,
dense_rank() over(partition by customer_id order by cnt desc) as rn
from cte1
)
select customer_id, brand_id
from cte2
where rn = 1
sql fiddle demo
For PostgreSQL 8.3:
select distinct on (customer_id)
customer_id, brand_id, cnt
from (
select customer_id, brand_id, count(*) as cnt
from test1
group by customer_id, brand_id
) as c
order by customer_id, cnt desc;
sql fiddle demo

or like this
with cte as (
SELECT
transaction.customer_id,
count(transaction.brand_id) as occ,
FROM
transaction
GROUP BY
transaction.customer_id
)
select max(occ) from cte

Related

How to retrieve the most frequent value of a column for a specific ID in a table

I'm trying to fetch the most frequent value from a SQLite 3 database table for each specific ID (which is the ID of a company). I have tried with GROUP BY and ORDER BY as well as with COUNT() function.
SELECT company_id, max(car)
FROM car_orders
GROUP by company_id
ORDER by max(car)
For a specific company_id (9) I am expecting 'Audi' to be in result but this is not the case as its 'Volkswagen' (which is wrong)
Similar to your attempts, consider joining two aggregates that calculates COUNT per car and company and MAX of same counter per company. Below uses CTE introduced in SQLite in version 3.8.3, released in February 2014.
WITH cnt AS (
SELECT company_id, car, COUNT(*) AS car_count
FROM car_orders
GROUP by company_id, car
),
max_cnt AS (
SELECT cnt.company_id, MAX(cnt.car_count) as max_count
FROM cnt
GROUP BY cnt.company_id
)
SELECT cnt.company_id, cnt.car
FROM cnt
INNER JOIN max_cnt
ON cnt.company_id = max_cnt.company_id
AND cnt.car_count = max_cnt.max_count
In the more recent versions of SQLite, you can use window functions:
SELECT cc.*
FROM (SELECT company_id, car, COUNT(*) as cnt,
ROW_NUMBER() OVER (PARTITION BY company_id ORDER BY COUNT(*) DESC) as seqnum
FROM car_orders
GROUP by company_id, car
) cc
WHERE seqnum = 1;
In earlier versions, it is a little more complicated:
WITH cc as (
SELECT company_id, car, COUNT(*) as cnt
FROM car_orders
GROUP by company_id, car
)
SELECT cc.*
FROM cc
WHERE cc.cnt = (SELECT MAX(cc2.cnt)
FROM cc cc2
WHERE cc2.company_id = cc.company_id
);

Selecting City from Customer ID in SQL

Customer have ordered from different cities. Thus we have multiple cities against same customer_id. I want to display that city against customer id which has occurred maximum number of times , in case where customer has ordered same number of orders from multiple cities that city should be selected from where he has placed last order. I have tried something like
SELECT customer_id,delivery_city,COUNT(DISTINCT delivery_city)
FROM analytics.f_order
GROUP BY customer_id,delivery_city
HAVING COUNT(DISTINCT delivery_city) > 1
WITH cte as (
SELECT customer_id,
delivery_city,
COUNT(delivery_city) as city_count,
MAX(order_date) as last_order
FROM analytics.f_order
GROUP BY customer_id, delivery_city
), ranking as (
SELECT *, row_number() over (partition by customer_id
order by city_count DESC, last_order DESC) as rn
FROM cte
)
SELECT *
FROM ranking
WHERE rn = 1
select customer_id,
delivery_city,
amount
from
(
select t.*,
rank() over (partition by customer_id order by amount asc) as rank
from(
SELECT customer_id,
delivery_city,
COUNT(DISTINCT delivery_city) as amount
FROM analytics.f_order
GROUP BY customer_id,delivery_city
) t
)
where rank = 1

Group by clause with min

I am having the following table
I used following query and i got error message. I can identify why the error is but how can i solve it
select min(id),customer_id,created_at from thunderbolt_orders
group by customer_id
I need the minimum id's customer_id and created_at how can i achieve it.
select distinct on (customer_id)
customer_id, id, created_at
from thunderbolt_orders
order by customer_id, id
with cte as (
select
*, row_number() over(partition by customer_id order by id) as row_num
from Table1
)
select *
from cte
where row_num = 1
SELECT id,customer_id,created_at
FROM thunderbolt_orders
WHERE id IN
(SELECT MIN(id) FROM thunderbolt_orders GROUP BY customer_id);
Depending on whether or not you just want the minimum ID or whether you want the minimum ID for each customer these are the solutions.
Minimum ID:
select top 1 id,customer_id,created_at from thunderbolt_orders order by id asc
Minimum ID for each customer:
with cte as (
select min(id) as id
from thunderbolt_orders
group by customer_id
)
select *
from cte c
inner join thunderbolt_orders t on t.id = c.id

SQL Server Group By Complex Query

In SQL Server, suppose we have a SALES_HISTORY table as below.
CustomerNo PurchaseDate ProductId
1 20120411 12
1 20120330 13
2 20120312 14
3 20120222 16
3 20120109 16
... and many records for each purchase of each customer...
How can I write the appropriate query for finding:
For each customer,
find the product he bought at MOST,
find the percentage of this product over all products he bought.
The result table must have columns like:
CustomerNo,
MostPurchasedProductId,
MostPurchasedProductPercentage
Assuming SQL Server 2005+, you can do the following:
;WITH CTE AS
(
SELECT *,
COUNT(*) OVER(PARTITION BY CustomerNo, ProductId) TotalProduct,
COUNT(*) OVER(PARTITION BY CustomerNo) Total
FROM YourTable
), CTE2 AS
(
SELECT *,
RN = ROW_NUMBER() OVER(PARTITION BY CustomerNo
ORDER BY TotalProduct DESC)
FROM CTE
)
SELECT CustomerNo,
ProductId MostPurchasedProductId,
CAST(TotalProduct AS NUMERIC(16,2))/Total*100 MostPurchasedProductPercent
FROM CTE2
WHERE RN = 1
You still need to deal when you have more than one product as the most purchased one. Here is a sqlfiddle with a demo for you to try.
Could do a lot prettier, but it works:
with cte as(
select CustomerNo, ProductId, count(1) as c
from SALES_HISTORY
group by CustomerNo, ProductId)
select CustomerNo, ProductId as MostPurchasedProductId, (t.c * 1.0)/(select sum(c) from cte t2 where t.CustomerNo = t2.CustomerNo) as MostPurchasedProductPercentage
from cte t
where c = (select max(c) from cte t2 where t.CustomerNo = t2.CustomerNo)
SQL Fiddle

Return top 5 from SUM in select statement

I need to return the following statement but I only want to return the TOP 5 of each Sale value only.....not all the records.
Select ID, Code, sum(Sale) as Sale from TableName
Where Code = 11
Group By ID, code
I do not want this!
Select TOP 5 ID, Code, sum(Sale) as Sale from TableName
Where Code = 11
Group By ID, code
With Cte as
( Select ID, Code, sale as Sales ,
row_number() over (partition by ID,code order by sale desc) as row_num
from TableName where code=11
)
Select Id,code,sum(sales) from cte
GROUP BY ID, code
WHERE row_num < 6
WITH TopSales AS (
SELECT *, RANK() OVER (PARTITION BY ID, Code ORDER BY Sale DESC) saleRank
FROM TableName
)
SELECT ID, Code, SUM(Sale) AS Sale
FROM TopSales
WHERE (Code = 11) AND (saleRank <= 5)
GROUP BY ID, code
select id, code, SUM (sale)
from
(
select id, code, sale,
ROW_NUMBER() over(partition by id, code order by sale desc) rn
from tablename
) v
where rn<=5
group by id, code
Probably you need something like:
;WITH sales (
SELECT
id,
code,
sale,
ROW_NUMBER() OVER (PARTITION BY id, code ORDER BY sales DESC) n
FROM
TableName
WHERE
Code = 11
)
SELECT
id, code, sum(sale) sale
FROM
sales
WHERE
n <= 5
GROUP BY
id,
code
ROW_NUMBER() and PARTITION BY help to find last 5 sales. Then you SUM only top (highest) 5.
This query returns sum of top 5 sales for each (id, code) group.
If you want to return just the top 5 results for each group you could do this:
with cte as
(ID, Code, Sale,ROW_NUMBER() over(partition by ID,
Code order by (select 0)) rownum
from TableName)
Select ID, Code, sum(Sale) as Sale from cte
Where Code = 11
and rownum<=5
Group By ID, code
If you want to return top 5 results with highest salary for each group you could do this:
with cte as
(ID, Code, Sale,ROW_NUMBER() over(partition by ID,
Code order by Sale desc) rownum
from TableName)
Select ID, Code, sum(Sale) as Sale from cte
Where Code = 11
and rownum<=5
Group By ID, code
select id, code, sum(sale) as sale from tablename
where code = 11
group by id, code
order by sum(sale) desc
limit 5