How to query count(customer), count(order) pair - sql

Assuming we have tables
Order(customerId,orderDetails...)
Customer(Id, customerDetails...)
What is the easiest way to query Count(customer)xCount(order) pair?
example
Customer:
ID | Name
---------
1 | Bob
2 | Ann
Order
CustomerId | Address
--------------------
1 | Block1
1 | Block2
1 | Block1
2 | Home Address
Want to get
CustomerCount | OrderCount
--------------------------
1 | 3
1 | 1

How about
SELECT DISTINCT COUNT(DISTINCT c.ID) AS CustomerCount
, COUNT(*) AS OrderCount
FROM Customer AS c
INNER JOIN [Order] AS o ON o.customerID = c.ID
GROUP BY
c.ID
SQL Fiddle
Edit
Coming to think of it, the previous statement can be reduced to this
SELECT DISTINCT 1 AS CustomerCount
, COUNT(*) AS OrderCount
FROM Customer AS c
INNER JOIN [Order] AS o ON o.customerID = c.ID
GROUP BY
c.ID
but that gives me a nagging feeling that my initial statement is wrong to begin with

select order.id, count(.CustomerId )
from Order order left join Customer customer on order.id = customer.CustomerId
group by order.id

Related

Select Customer Name From Customer Table and Count all Orders placed using orders table- SQL

I have two table as defined below,
Table: Customer:
CustomerID | CustomerName |
--------------------------
1 | John
2 | Mack
3 | Andy
Table: Orders:
OrderID | CustomerID|
--------------------------
1515 | 1
1516 | 3
1517 | 1
1518 | 1
1519 | 3
1520 | 1
I want to write a query to select each name and count of all orders placed by each customer using JOIN. the result will be,
John | 4
Mack | 0
Andy | 2
My query:
SELECT
CustomerName, Count(*)
FROM
Orders
INNER JOIN
Customers WHERE Orders.CustomerID = Customers.CustomerID;
But its returning incorrect results. Please advise.
You are missing the GROUP BY. I would write the query like this:
SELECT c.CustomerName, Count(o.CustomerId)
FROM Customers c LEFT JOIN
Orders o
ON o.CustomerID = c.CustomerID
GROUP BY c.CustomerName;
Notes:
Table aliases (c and o) make the query easier to write and to read.
The LEFT JOIN keeps all customers, even those without orders. If you don't want 0 counts, then change to an INNER JOIN.
All joins should have an ON clause, not a WHERE clause for the JOIN conditions.
The GROUP BY is also needed to fix your query attempt.
Use:
SELECT Customers.CustomerName, Count(*)
FROM Orders LEFT OUTER JOIN Customers
WHERE Orders.CustomerID=Customers.CustomerID GROUP BY Customers.CustomerName;
SELECT CustomerName,ISNULL(_Count,0) [Count]
FROM Customer
LEFT OUTER JOIN
(
SELECT COUNT(*) _Count,CustomerId _CustomerId
FROM Orders
GROUP BY CustomerId
) A ON _CustomerId = CustomerID

How can I select customers who have certain number of orders and other conditions?

I am studying SQL. There is one particular query which I find difficult to implement (using PostgreSQL database).
Could someone help me with that?
Query : "Who are the customers who have at least one order which includes products from at least 3 product categories?".
The result should include 2 columns: customerID and Quantity of orders.
The tables are the following:
Product ProductID (id of a product)|ProductCategoryID (product categories) both integers.
SalesOrderDetail :SalesOrderID (id order)|SalesOrderDetailID|OrderQty|ProductID, all of them integers .
SalesOrderHeader: SalesOrderID|CustomerID, both integers.
The only thing I got so far is the first part of the statement:
select salesorderheader.customerID, salesorderdetail.orderqty
from salesorderheader, salesorderdetail;
Sample data:
productid | productcategoryid
-----------+-------------------
1 | 2
2 | 2
3 | 3
4 |
salesorderid | salesorderdetailid | orderqty | productid
--------------+--------------------+----------+-----------
43659 | 1 | 1 | 776
43659 | 2 | 3 | 777
43659 | 3 | 1 | 778
salesorderid | customerid
--------------+------------
43659 | 29825
43660 | 29672
43661 | 29734
I see two approaches here:
1) Generate a subquery which contains the count a salesOrderID and the count of Distinct ProductCategories used for that salesorder.
SELECT customerID, count(Distinct OH.SalesOrderID) SalesOrdersWithMoreThan3Categories
FROM SalesOrderHeader OH
INNER JOIN (SELECT OD.SalesOrderID, Count(Distinct P.ProductCategoryID) Cnt
FROM SalesOrderDetail OD
INNER JOIN Product P
on P.ProudctID = OD.ProductID
GROUP BY OD.SalesOrderID) B
on OH.SalesOrderID = B.SaleOrderID
and B.cnt >=3
GROUP BY OH.customerID
2) Use Exists to identify orderDetails a count of distinct productCategories >=3
SELECT OH.customerID, count(Distinct OH.SalesOrderID) SalesOrdersWithMoreThan3Categories
FROM SalesOrderHeader OH
WHERE exists (SELECT 1
FROM SalesOrderDetail OD
INNER JOIN Product P
on P.ProudctID = OD.ProductID
WHERE OH.SalesOrderID = OD.SalesOrderID
GROUP BY OD.SalesOrderID
HAVING Count(Distinct P.ProductCategoryID) >=3)
GROUP BY OH.customerID

two counts in group by

I want to find for each store the number of products for that store/number of customers of that store
Customer
Id | dealerId
1 | 10
2 | 11
3 | 10
Product
Id | CustomerId
100 | 1
200 | 3
300 | 2
store
Id
10
11
The result for the above example would be:
StoreId | value
10 | 2/2
11 | 1/1
SELECT
c.dealerID as Store,
COUNT(DISTINCT c.ID) as NumOfCustomers,
COUNT(p.ID) as NumOfProducts
FROM
Customers C
INNER JOIN
Products p on p.CustomerId = c.Id
GROUP BY
c.dealerID
select S.Id AS StoreId, COUNT(p.Id) AS ProductId, COUNT(CAST.Id) AS CustomerId
from Store S
left join Customer C on C.dealerId = Scheduler.StoreId
left join Product P on P.CustomerId = CAST.Id
group by S.Id

How to calculate max(column) row from a result set grouped by different items

SELECT T1.* FROM
(
SELECT
MAX(no_of_orders) [no_of_orders],
ord.customer_id [customer_id],
ord_dtl.item_id [item_id]
FROM order_main ord
INNER JOIN order_detail ord_dtl
ON ord.order_id = ord_dtl.order_id
GROUP BY
ord.customer_id, ord_dtl.item_id
) T1
INNER JOIN
(
SELECT
MAX(no_of_orders) [no_of_orders],
ord.customer_id
FROM order_main ord
INNER JOIN order_detail ord_dtl
ON ord.order_id = ord_dtl.order_id
GROUP BY
ord.customer_id
) T2
ON
T1.customer_id = T2.customer_id
AND T1.no_of_orders = T2.no_of_orders
I calculated the most ordered item by customer from table order_main and order_detail.
What I did is like I calculated the no of orders grouping by customer id and item id and to reduce the result set to most ordered item by customer, I joined the resultset by same query removing the grouping by item id.
I don't feel this is a good query.
Any better alternative ?
SQL Fiddle
Most ordered item by customer
Query:
SQLFIDDLEExample
SELECT a.no_of_orders,
a.customer_id,
a.item_id
FROM (SELECT
MAX(no_of_orders) [no_of_orders],
ord.customer_id [customer_id],
ord_dtl.item_id [item_id],
ROW_NUMBER() OVER(PARTITION BY ord.customer_id ORDER BY MAX(no_of_orders) DESC) AS rnk
FROM order_main ord
INNER JOIN order_detail ord_dtl
ON ord.order_id = ord_dtl.order_id
GROUP BY
ord.customer_id, ord_dtl.item_id) a
WHERE a.rnk = 1
Result:
| NO_OF_ORDERS | CUSTOMER_ID | ITEM_ID |
---------------|-------------|---------|
| 20 | 2 | 6 |
| 50 | 7 | 6 |
| 1500 | 8 | 7 |
| 10 | 9 | 3 |

Refactor SQL query to return results into rows instead of columns

I have a SQL query that need to be refactored. Basically the query gets all the producttypes ordered by a specified customer. The problem is that the results are returned in columns instead of rows. This needs to be changed the other way around to make the query more generic.
So this is what the query returns:
Name ProductType1 ProductType2 ProductType3
--------------------------------------------------
Marc PT09 P15 PT33
And this is what it should be:
Name ProductType
----------------
Marc PT09
Marc P15
Marc PT33
This is the query which I have simplified a bit:
SELECT
CustomerData.Name as Name
Product1.productType as ProductType1,
Product2.productType as ProductType2,
Product3.productType as ProductType3
FROM
(SELECT ProductID, Name
FROM
Customer
Orders
WHERE Customer.ID = 111
) as CustomerData
LEFT JOIN (SELECT DISTINCT CP.ProductID as ProductID,
PC.Type as ProductType
FROM
CustomerProduct CP,
ProductCategory PC
WHERE
PC.Category = 'A'
AND CP.ProductCategoryID = PC.ID
) as Product1
on CustomerData.ProductID = Product1.ProductID
LEFT JOIN (SELECT DISTINCT CP.ProductID as ProductID,
PC.Type as ProductType
FROM
CustomerProduct CP,
ProductCategory PC
WHERE
PC.Category = 'B'
AND CP.ProductCategoryID = PC.ID
) as Product2
on CustomerData.ProductID = Product1.ProductID
LEFT JOIN (SELECT DISTINCT CP.ProductID as ProductID,
PC.Type as ProductType
FROM
CustomerProduct CP,
ProductCategory PC
WHERE
PC.Category = 'C'
AND CP.ProductCategoryID = PC.ID
) as Product3
on CustomerData.ProductID = Product1.ProductID
So I have been thinking about splitting the joins into a separate stored proc and then call this as I need more productTypes but I can't seem to get this working. Anyone an idea on how to get this working ?
Doing things in columns is actually usually much more difficult.
Assuming normalized tables Customers, Products and Orders, you shouldn't need to do anything more than just:
SELECT C.customer_name
, P.product_type
FROM Customers C
JOIN Orders O
ON O.customer_id=C.customer_id
JOIN Products P
ON O.product_id=P.product_id
WHERE C.ID = 111
If this doesn't work, please list structures of the involved tables.
I'm going to assume your tables looks something like this
Customer
id | name
11 | Marc
Products
id | type
21 | PT09
22 | P15
23 | PT33
Orders
id | id_customer | id_product | quantity
31 | 11 | 21 | 4
32 | 11 | 22 | 6
33 | 11 | 23 | 8
Then your query is
SELECT
a.name,
c.type
FROM
Customer a
LEFT JOIN
Orders b ON b.id_customer = a.id
LEFT JOIN
Products c ON c.id = b.id_product