Repeated elements counting for Sql datatables queries - sql

I have 2 tables: an Order table and an orderDetails table.
I have written a inner join:
SELECT Order.id
FROM Order
INNER JOIN orderDetails
ON Order.id=orderDetails.id
I have got the output as:
id
100
100
100
101
101
From the above data, I want the count of each record output as:
id count
100 3
101 2
How would I do this?

Select OrderId , Count(*) as [Count]
from OrderDetials
Group By OrderId
OrderId will be a foreing key column referencing Order.Id column of Order Table
If your orderDetails.id references Order.id column This will be the query.
Select id , Count(*) as [Count]
from OrderDetials
Group By id

SELECT o.id, COUNT(*)
FROM Order o
JOIN orderDetails od ON o.id=od.id
GROUP BY o.id

You need to use the COUNT aggregate and the GROUP BY clause.
SELECT Order.id, COUNT(DISTINCT orderDetails.id)
FROM Order
INNER JOIN orderDetails ON Order.id=orderDetails.orderId
GROUP BY Order.id
It also looks like you need o alter the join condition slightly.

Use Group by
SELECT Order.id, count(*) as Count
FROM Order
INNER JOIN orderDetails
ON Order.id=orderDetails.id Group by Order.id

Related

SQL 2 Rows into 1

Below is a SQL script to see how many customers purchased both products, as well as how many customers purchased either of the two products.
I would like to be able to return a result set with one column for the first product, one column for the second, one column for Count with Both, and one column for Count with Either.
Instead it returns a column for each of the counts and a single NULL column for the ProductID.
SELECT
COUNT(DISTINCT b.CustomerID) AS "Count with Both",
COUNT(DISTINCT c.CustomerID) AS "Count with Either",
b.ProductID
FROM
LocationCode z
LEFT JOIN
(SELECT DISTINCT ProductID, CustomerID
FROM LocationCode a
WHERE a.ProductID IN ('MP040') AND a.ProductID IN ('OG010')) b ON z.CustomerID = b.CustomerID
LEFT JOIN
(SELECT DISTINCT ProductID, CustomerID
FROM LocationCode b
WHERE b.ProductID IN ('MP040', 'OG010')) c ON z.CustomerID = c.CustomerID
GROUP BY
b.ProductID
If I understand correctly, you can use a self-join and aggregation. The following does what you want for all pairs of products:
with cp as (
select customerid, productid,
count(*) over (partition by customerid) as num_customers
from locationcode
group by customerid, productid
)
select cp1.productid, cp2.productid, cp1.cnt as cnt1, cp2.cnt as cnt2,
count(*) as both
from cp cp1 join
cp cp2
on cp1.customerid = cp2.customerid and
cp1.productid < cp2.productid
group by cp1.productid, cp2.productid, cp1.cnt, cp2.cnt ;
You can of course add where filters if you only want results for certain products.

SQL Server Query Count Join Table

I have 2 tables are call Suppliers and Products, which products have SupplierID as foreign key.
My question is how to make a query that can show this result
Supplier Name | Total Products
--------------+---------------
Unilever | 20
Kalbe | 50
Jhonson | 70
My table structure
Suppliers => ID, Name
Products => ID, SupplierID, Brand, Price
This is what I tried:
SELECT COUNT(*) AS Total
FROM Products
GROUP BY SupplierID
select
s.Name as 'Supplier Name', count(p.ID) as 'Total Products'
from
Supliers as s
left outer join
Producsts as p on (s.Id = p.SupplierID)
group by
s.Name;
All you need in addition to your query is a sub-query to obtain the name:
SELECT COUNT(*) as Total
, (select Name from Supplier where ID = SupplierID) as [Supplier Name]
FROM Products
GROUP BY SupplierID
you can use left join by SuplierID + subquery for Products group by SuplierID to avoid multi slow query.
select T1.Name as Supplier Name
,T2.cnt as Total Product
from Supliers T1
left join (
select SuplierID,count(1) cnt
from Products
group by SuplierID
) T2 on T1.ID = T2.SuplierID

sqlerrorColumn 'tableName' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause

I have three tables
Table 1:
tblCustomer
CustomerID CustomerName
1 ABC Bank
2 Chase Bank
Table 2:
tblOrderType
OrderTypeID OrderTypeName
1 Assignment
2 LienRelease
Table 3:
tblOrder
OrderID CustomerID OrderTypeID LoanNumber
1 1 1 45584565
2 1 1 45566856
3 1 1 45565584
4 1 1 45588545
I am trying to return CustomerID, CustomerName, OrderTypeName and OrderCount in CustomerName order but when using the following query:
SELECT tblOrder.CustomerID,CustomerName,OrderTypeName,COUNT(tblOrder.CustomerID) FROM tblOrder
INNER JOIN tblCustomer ON tblOrder.CustomerID=tblCustomer.CustomerID
INNER JOIN tblOrderType ON tblOrder.OrderTypeID=tblOrderType.OrderTypeID
GROUP BY tblOrder.CustomerID
I am getting the error:
Column 'tblCustomer.CustomerName' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
I dont know what I am doing wrong.
Your SELECT and GROUP BY statements should have same fields. In your case
SELECT tblOrder.CustomerID,CustomerName,OrderTypeName
The answer is exactly what the error message is telling you.
You cannot select columns which aren't in the group by clause OR aggregated by somehow.
You also haven't included the actual order by clause.
SELECT
tblOrder.CustomerID,
tblCustomer.CustomerName,
tblOrderType.OrderTypeName,
COUNT(tblOrder.CustomerID)
FROM
tblOrder
INNER JOIN tblCustomer ON tblOrder.CustomerID=tblCustomer.CustomerID
INNER JOIN tblOrderType ON tblOrder.OrderTypeID=tblOrderType.OrderTypeID
GROUP BY
tblOrder.CustomerID,
tblCustomer.CustomerName,
tblOrderType.OrderTypeName,
ORDER BY
tblCustomer .CustomerName ASC
If you use GROUP BY in SQl-Server you have to aggregate all selected columns(f.e. with Min, Max, Count etc) or you have to include them in the GROUP BY. That makes sense because it's not clear which row's value you want to take for CustomerName and OrderTypeName, there could be multiple for each id-group.
If that's not the case include it in the Group by:
SELECT tblOrder.CustomerID,
CustomerName,
OrderTypeName,
COUNT(tblOrder.CustomerID) As CountCustomerID
FROM tblOrder
INNER JOIN tblCustomer ON tblOrder.CustomerID=tblCustomer.CustomerID
INNER JOIN tblOrderType ON tblOrder.OrderTypeID=tblOrderType.OrderTypeID
GROUP BY tblOrder.CustomerID, CustomerName, OrderTypeName
Another way in SQL-Server(>=2005) is using a CTE(or subquery) + ROW_NUMBER, then you can select all fields:
WITH CTE AS
(
SELECT tblOrder.CustomerID,
CustomerName,
OrderTypeName,
Count(*) OVER (PARTITION BY tblOrder.CustomerID, CustomerName, OrderTypeName),
RN = ROW_NUMBER() OVER (PARTITION BY tblOrder.CustomerID, CustomerName, OrderTypeName
ORDER BY CustomerID, CustomerName)
FROM tblOrder
INNER JOIN tblCustomer ON tblOrder.CustomerID=tblCustomer.CustomerID
INNER JOIN tblOrderType ON tblOrder.OrderTypeID=tblOrderType.OrderTypeID
)
SELECT * FROM CTE
WHERE RN = 1
You need to aggregate the columns that are not included in your GROUP BY statement:
SELECT A.CUSTOMERID, MAX(B.CUSTOMERNAME), MAX(C.ORDERTYPENAME), COUNT(A.CUSTOMERID)
FROM TBLORDER AS A
INNER JOIN TBLCUSTOMER AS B
ON A.CUSTOMERID=B.CUSTOMERID
INNER JOIN TBLORDERTYPE AS C
ON A.ORDERTYPEID=C.ORDERTYPEID
GROUP BY A.CUSTOMERID
Or you can group by the same columns in your SELECT.
Something like this
SELECT tblOrder.CustomerID, CustomerName, OrderTypeName, COUNT(*)
FROM tblOrder
INNER JOIN tblCustomer ON tblOrder.CustomerID=tblCustomer.CustomerID
INNER JOIN tblOrderType ON tblOrder.OrderTypeID=tblOrderType.OrderTypeID
GROUP BY tblOrder.CustomerID, CustomerName, OrderTypeName
or this
SELECT tblOrder.CustomerID, CustomerName, COUNT(*)
FROM tblOrder
INNER JOIN tblCustomer ON tblOrder.CustomerID = tblCustomer.CustomerID
GROUP BY tblOrder.CustomerID, CustomerName

SQL Query for counting number of orders per customer and Total Dollar amount

I have two tables
Order with columns:
OrderID,OrderDate,CID,EmployeeID
And OrderItem with columns:
OrderID,ItemID,Quantity,SalePrice
I need to return the CustomerID(CID), number of orders per customer, and each customers total amount for all orders.
So far I have two separate queries. One gives me the count of customer orders....
SELECT CID, Count(Order.OrderID) AS TotalOrders
FROM [Order]
Where CID = CID
GROUP BY CID
Order BY Count(Order.OrderID) DESC;
And the other gives me the total sales. I'm having trouble combining them...
SELECT CID, Sum(OrderItem.Quantity*OrderItem.SalePrice) AS TotalDollarAmount
FROM OrderItem, [Order]
WHERE OrderItem.OrderID = [Order].OrderID
GROUP BY CID
I'm doing this in Access 2010.
You would use COUNT(DISTINCT ...) in other SQL engines:
SELECT CID,
Count(DISTINCT O.OrderID) AS TotalOrders,
Sum(OI.Quantity*OI.SalePrice) AS TotalDollarAmount
FROM [Order] O
INNER JOIN [OrderItem] OI
ON O.OrderID = OI.OrderID
GROUP BY CID
Order BY Count(DISTINCT O.OrderID) DESC
Which Access unfortunately does not support. Instead you can first get the Order dollar amounts and then join them before figuring the order counts:
SELECT CID,
COUNT(Orders.OrderID) AS TotalOrders,
SUM(OrderAmounts.DollarAmount) AS TotalDollarAmount
FROM [Orders]
INNER JOIN (SELECT OrderID, Sum(Quantity*SalePrice) AS DollarAmount
FROM OrderItems GROUP BY OrderID) AS OrderAmounts
ON Orders.OrderID = OrderAmounts.OrderID
GROUP BY CID
ORDER BY Count(Orders.OrderID) DESC
If you need to include Customers that have orders with no items (unusual but possible), change INNER JOIN to LEFT OUTER JOIN.
Create a query which uses your 2 existing queries as subqueriers, and join the 2 subqueries on CID. Define your ORDER BY in the parent query instead of in a subquery.
SELECT
sub1.CID,
sub1.TotalOrders,
sub2.TotalDollarAmount
FROM
(
SELECT
CID,
Count(Order.OrderID) AS TotalOrders
FROM [Order]
GROUP BY CID
) AS sub1
INNER JOIN
(
SELECT
CID,
Sum(OrderItem.Quantity*OrderItem.SalePrice)
AS TotalDollarAmount
FROM OrderItem INNER JOIN [Order]
ON OrderItem.OrderID = [Order].OrderID
GROUP BY CID
) AS sub2
ON sub1.CID = sub2.CID
ORDER BY sub1.TotalOrders DESC;

sql query with two tables having reference key

I have two tables:
Discounts(disid primary key)
Cust(custid primary key, disid ref discount(disid))
Now I need a query to get custid having all disid(discount coupons) and the customer may contain the same disid more than once.
select custid, count(distinct disid) from cust
group by custid
having count(*) = (select count(*) from discounts)
SELECT COUNT(DISTINCT D.disid) FROM CUST C
INNER JOIN DISCOUNTS D ON D.disid=C.disid GROUP BY D.disid
try either of this solutions:
SELECT a.custid, COUNT(a.disid) totalCoupon
FROM cust a
INNER JOIN discounts b
ON b.disid = a.disid
GROUP BY a.custid
or
SELECT a.custid, COUNT(a.disid) totalCoupon
FROM cust a
INNER JOIN discounts b
ON b.disid = a.disid
GROUP BY a.custid
HAVING COUNT(a.disid) > 1 -- customers having the same (but more than 1)
-- CouponID will only be shown here