SQL Server inner join after Count and GroupBy - sql

I'm trying to make an eCommerce web site. And at ProductCategory page I have to do a list about Companies that included by Products.
I have a Product table that contains:
ProductID
ProductName
...
MarkID
And I have a Company table that contains:
CompanyID
CompanyName
I want to mix them in a query.
After that code block,
SELECT
CompanyID,
count(CompanyID) as CompanyCount
FROM
Products
GROUP by
CompanyID
I get this result:
CompanyID CompanyCount
-------------------------
1 2
3 1
4 4
after that I just want to inner join that with CompanyName
And want a result like this:
CompanyName CompanyCount
---------------------------
1 2
3 1
4 4
How can I do that?

With a subquery:
SELECT * FROM
(
SELECT CompanyID, count(CompanyID) as CompanyCount
FROM Products
GROUP by CompanyID
) CompanyCounts
INNER JOIN Companies
on CompanyCounts.CompanyId = Companies.CompanyID
If you need this in more places, you may want to create a view for company count.

This can be achieved without a subquery.
SELECT C.CompanyID, C.CompanyName, COUNT(*)
FROM Products P INNER JOIN Companies C ON P.CompanyId = C.CompanyID
GROUP BY C.CompanyID, C.CompanyName

You can use your first select as a subquery to join with Companies table:
SELECT C.CompanyName, Q1.CompanyCount
FROM Companies C
JOIN (
SELECT CompanyID, count(CompanyID) as CompanyCount
FROM Products
GROUP by CompanyID
) Q1
ON Q1.CompanyID = C.CompanyId

Related

Select same column from multiple tables with condition and LEFT JOIN

I have two tables with fiew similar columns :
One is for SellOrders
OrderID (PK)| id_seller| id_product| placement_date
And the other is for BuyOrders
OrderID (PK)| id_buyer| id_product| placement_date
With another table Customer concerning customers informations (Buyers and sellers)
id_customer(PK) | name_customer
And a Product table :
id(PK) | name_product
I want to write an SQL statement that will select the first placement_date when the a buy order or sell order was placed for the product and the correspending name_customer + the name_product.
I wrote a query that select the same logic but for only the selling side and I am looking to select the data for both buy and sell side :
SELECT p.name_product, s.placement_date, c.name_customer
FROM Product p
OUTER APPLY (SELECT TOP 1 placement_date, id_seller
FROM Selling
WHERE id_product = p.id
ORDER BY placement_date, OrderID ASC) s
LEFT JOIN Customer c
ON c.id_customer = s.id_seller
From what I have seen UNION SELECT seems to be the way to do this. I added UNION to the OUTER APPLY:
OUTER APPLY (SELECT TOP 1 placement_date, id_seller
FROM Selling
UNION
SELECT TOP 1 placement_date, id_buyer
WHERE id_product = p.id
ORDER BY placement_date, OrderID ASC) s
But I get stuck at the LEFT JOIN with the table Customer.
Any help ?
If I've got it right you want first of union of buy/sell orders
SELECT p.name_product, s.placement_date, c.name_customer
FROM Product p
OUTER APPLY (
SELECT TOP 1 placement_date, id_cust
FROM (
SELECT placement_date, OrderID, id_seller id_cust
FROM SellOrders
WHERE id_product = p.id
UNION
SELECT placement_date, OrderID, id_buyer
FROM BuyOrders
WHERE id_product = p.id
) t
ORDER BY placement_date, OrderID ASC
) s
LEFT JOIN Customer c
ON c.id_customer = s.id_cust

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

How to get the count and display only one row

I've got 3 Tables:
tblCustomer
CustomerID CustomerName
1 Customer 1
2 Customer 2
tblOrder
OrderID CustomerID OrderTypeID LoanNumber
1 1 1 98513542
2 1 1 71283527
3 1 1 10268541
4 1 1 61258965
tblOrderType
OrderTypeID OrderTypeName
1 Purchase
2 Rental
Now, I'm looking to return CustomerID, CustomerName, OrderTypeName and OrderCount, where OrderCount is how many of each order the customer has. I'm using the following query:
SELECT tblCustomer.CustomerID, tblCustomer.customerName, tblOrderType.OrderTypeName, tblOrder.OrderID
FROM tblCustomer
INNER JOIN tblOrder
ON tblCustomer.CustomerID = tblOrder.CustomerID
INNER JOIN tblOrderType
ON tblOrderType.OrderTypeID = tblOrder.OrderTypeID
It sort of works. It gets all I'm asking for, except for the OrderCount, obviously. The result is like this:
CustomerID CustomerName OrderTypeName OrderID
1 Customer 1 Purchase 1
1 Customer 1 Purchase 2
1 Customer 1 Purchase 3
1 Customer 1 Purchase 4
But what I'm looking for is this:
CustomerID CustomerName OrderTypeName OrderCount
1 Customer 1 Purchase 4
Now, I've tried adding Count() into the query at various places (Count(tblOrder.OrderID) for one), and I get an error that tblCustomer.CustomerID is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
This isn't a homework assignment. I just don't know a whole lot about sql and database interactions, since it wasn't taught in my school, and I've got a friend who's throwing scenarios at me.
You need to use grouping and aggregation:
SELECT tblCustomer.CustomerID, tblCustomer.customerName, tblOrderType.OrderTypeName,
count (tblOrder.OrderID) asOrderCOunt
FROM tblCustomer
INNER JOIN tblOrder
ON tblCustomer.CustomerID = tblOrder.CustomerID
INNER JOIN tblOrderType
ON tblOrderType.OrderTypeID = tblOrder.OrderTypeID
GROUP BY
tblCustomer.CustomerID,
tblCustomer.customerName,
tblOrderType.OrderTypeName
You can't use aggregate functions without grouping everything that isn't aggregated.
The error message does tell you the issue. Whenever you use an aggregation operator (COUNT, SUM, AVG, etc.), you have to tell the database how these should be aggregated together. You do this with a GROUP BY statement (the link there is for SQL Server, but it should generally apply to all database engines):
SELECT
C.CustomerID
,C.customerName
,OT.OrderTypeName
,COUNT(O.OrderID)
FROM tblCustomer C
INNER JOIN tblOrder O
ON C.CustomerID = O.CustomerID
INNER JOIN tblOrderType OT
ON OT.OrderTypeID = O.OrderTypeID
GROUP BY
C.CustomerID
,C.customerName
,OT.OrderTypeName
Try this, just add group by and count the grouped rows
SELECT tblCustomer.CustomerID, tblCustomer.customerName,
tblOrderType.OrderTypeName, tblOrder.OrderID,
COUNT(tblOrder.OrderID) as OrderCount
FROM tblCustomer INNER JOIN tblOrder
ON tblCustomer.CustomerID = tblOrder.CustomerID
INNER JOIN tblOrderType
ON tblOrderType.OrderTypeID = tblOrder.OrderTypeID
GROUP BY tblCustomer.CustomerID, tblCustomer.customerName,
tblOrderType.OrderTypeName

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