Creating a pivot table in SQL with multiple JOINS [duplicate] - sql-server

Consider This Query:
SELECT [Order Details].OrderID,
c.CategoryName,
COUNT(c.CategoryID)
FROM [Order Details]
INNER JOIN Products p
ON p.ProductID = [Order Details].ProductID
INNER JOIN Categories c
ON c.CategoryID = p.CategoryID
GROUP BY
[Order Details].OrderID,
c.CategoryName
ORDER BY
[Order Details].OrderID
this query returns this such result (Usnig Northwind Database):
I want to use Pivot with Join to get such this result:
OrderID Condiments Produce Seafood Condiments Grains/Cereals ...
--------------------------------------------------------------------------------------
10250 1 1 1 0 0 ...
10251 1 0 0 0 2 ...
...
How I can do this?
Thanks

WITH T
AS (SELECT [Order Details].OrderID,
c.CategoryName,
c.CategoryID
FROM [Order Details]
INNER JOIN Products p
ON p.ProductID = [Order Details].ProductID
INNER JOIN Categories c
ON c.CategoryID = p.CategoryID)
SELECT *
FROM T PIVOT ( COUNT (CategoryID) FOR CategoryName IN (
[Beverages],
[Condiments],
[Confections],
[Dairy Products],
[Grains/Cereals],
[Meat/Poultry],
[Produce],
[Seafood]) ) AS pvt
ORDER BY OrderID

Related

Select all CustomerNames that have bought all the products that have been bought by the Customer with the id 'CENTC'

I am using the Northwind database
For now i have tried
It is where i select the Orders of the Client
select od.ProductID from Customers c JOIN
Orders o on c.CustomerID=o.CustomerID
JOIN [Order Details] od on o.OrderID=od.OrderID
where c.CustomerID='CENTC'
And here is my solution
select distinct c.CompanyName, sum(od.ProductID) as suma from Customers c JOIN
Orders o on c.CustomerID=o.CustomerID
JOIN [Order Details] od on o.OrderID=od.OrderID
where od.ProductID = '40' or od.ProductID = '11'
group by c.CompanyName
having sum(od.ProductID)='51'
But it's a one use solution so i am not satisfied.
You can use an IN subquery for this
SELECT
c.CompanyName,
c.ContactName,
SUM(od.quantity) AS quantity
FROM Customers c
JOIN Orders o on c.CustomerID = o.CustomerID
JOIN OrderDetails od on o.OrderID = od.OrderID
WHERE od.ProductID IN (
SELECT od2.ProductID
FROM Orders o2
JOIN OrderDetails od2 on o2.OrderID = od2.OrderID
WHERE o2.CustomerID = 'CENTC'
)
GROUP BY
c.CustomerID,
c.CompanyName,
c.ContactName;

How to use custom field from subquery in WHERE condition of upper level SELECT in SQL

I'm trying to do something like this but got an error and can't get how to do the last WHERE in the right way?
SELECT *
FROM
(
SELECT s.SupplierID, s.CompanyName,
(SELECT COUNT(*)
FROM dbo.Orders o
LEFT JOIN dbo.[Order Details] od ON o.OrderID = od.OrderID
LEFT JOIN dbo.Products p ON od.ProductID = p.ProductID
WHERE SupplierID = s.SupplierID) AS N'Number of orders'
FROM dbo.Suppliers s
)
WHERE 'Number of orders' > 150;
This is pretty sparse on details here but I think you are just trying to find and suppliers who have more than 150 orders. You can use a query with basic aggregation here and make this a lot simpler.
SELECT s.SupplierID
, s.CompanyName
, COUNT(*)
FROM dbo.Orders o
JOIN dbo.[Order Details] od ON o.OrderID = od.OrderID
JOIN dbo.Products p ON od.ProductID = p.ProductID
join dbo.Suppliers s on s.SupplierID = p.SupplierID
group by s.SupplierID
, s.CompanyName
having count(*) > 150
You need to name the main expression with an alias.
For example, this works:
SELECT * FROM (SELECT 1 AS One) O WHERE One = 1
But this does not:
SELECT * FROM (SELECT 1 AS One) WHERE One = 1
Try this:
SELECT *
FROM
(
SELECT s.SupplierID, s.CompanyName,
(SELECT COUNT(*)
FROM dbo.Orders o
LEFT JOIN dbo.[Order Details] od ON o.OrderID = od.OrderID
LEFT JOIN dbo.Products p ON od.ProductID = p.ProductID
WHERE SupplierID = s.SupplierID) AS N'Number of orders'
FROM dbo.Suppliers s
) T
WHERE 'Number of orders' > 150;
Also, as Uueerdo puointed out, it would be better to use [Square Brackets] instead of 'Single Quotes' to name and refer to the column [Number of orders]. I believe there is a setting that determines if single quotes are allowed, but square brackets are the standard.

Give the name of customers who bought ALL products with price less than 5

I want to write a query that give names of those customers only who have bought all products whose price is less than 5. Whereas, my query gives all customers who have bought even a single product whose price is less than 5.
SELECT Customers.CompanyName AS Customers
FROM Customers
INNER JOIN Orders
ON Orders.CustomerID = Customers.CustomerID
JOIN [Order Details]
ON [Order Details].OrderID = Orders.OrderID
JOIN Products
ON Products.ProductID = [Order Details].ProductID
WHERE [Order Details].ProductID IN (
SELECT Products.ProductID FROM Products WHERE Products.UnitPrice < 5
)
You can try the following:
SELECT Customers.CompanyName AS Customers
FROM Customers
INNER JOIN Orders
ON Orders.CustomerID = Customers.CustomerID
JOIN [Order Details]
ON [Order Details].OrderID = Orders.OrderID
JOIN Products
ON Products.ProductID = [Order Details].ProductID
WHERE [Order Details].ProductID IN (
SELECT Products.ProductID FROM Products WHERE Products.UnitPrice < 5)
GROUP BY CompanyName
HAVING COUNT([Order Details].ProductID) = (SELECT Count(Products.ProductID) FROM Products WHERE Products.UnitPrice < 5)
I Included the GROUP BY and Having Clause so that you can get only the customers who have bought all the products with unit price less than 5

Ranking customers by orders per customer and items per order

I'm trying to rank a query by not just one count, but by two.
I want to rank customers by the order items per orders.
WITH CTE AS
(
SELECT
o.CustomerId,
COUNT(DISTINCT o.OrderId) AS OrderCount,
COUNT(oi.OrderItemId) AS OrderItemCount
FROM
OrderItem oi
INNER JOIN
Order o ON o.OrderId = oi.OrderId
WHERE
o.CategoryId = 52 -- website sales
GROUP BY
o.CustomerId
)
SELECT
cust.Code,
cust.DisplayTitle,
CTE.OrderCount,
CTE.OrderItemCount,
--AVG(CTE.OrderItemCount/CTE.OrderCount) AS SumProduct ????
FROM
CTE
INNER JOIN
Customer cust ON cust.CustomerId = CTE.CustomerId
GROUP BY
cust.Code,
cust.DisplayTitle,
CTE.OrderCount,
CTE.OrderItemCount
ORDER BY
SumProduct DESC
I'm basically trying to implement the T-SQL equivalent of SUMPRODUCT() in Excel.
SELECT
o.CustomerId,
COUNT(DISTINCT o.OrderId) AS OrderCount,
COUNT(oi.OrderItemId) AS OrderItemCount,
COUNT(oi.OrderItemId) / COUNT(DISTINCT o.OrderId) avg
FROM OrderItem oi
INNER JOIN Order o ON o.OrderId = oi.OrderId
WHERE o.CategoryId = 52 -- website sales
GROUP BY o.CustomerId
order by COUNT(oi.OrderItemId) / COUNT(DISTINCT o.OrderId) desc
Just add in the join to customer

How I do SQL Pivot with respect to given query?

I'm working on SQL Server 2012. Trying to Pivot table data.
I have tried below following Query,
SELECT CategoryName, 1996_Val, 1997_Val
FROM(
SELECT
Categories.CategoryName,
Sum(CONVERT(money,("Order Details".UnitPrice*Quantity*(1-Discount)/100))*100) AS Sales,
YEAR(Orders.ShippedDate) AS ShippingYear
FROM Orders
INNER JOIN [Order Details] ON Orders.OrderID = [Order Details].OrderID
INNER JOIN Products ON [Order Details].ProductID = Products.ProductID
INNER JOIN Categories ON Products.CategoryID = Categories.CategoryID
WHERE (((Orders.ShippedDate) Between '19960101' And '19971231'))
GROUP BY Categories.CategoryID, Categories.CategoryName,YEAR(Orders.ShippedDate)
)p
PIVOT
(MAX(Sales) For ShippingYear IN(1996,1997)) AS pvt
ORDER BY Categories.CategoryID
which didn't work. Please help me...
I think you got the pivot a bit wrong. I think it should look something like this:
SELECT
*
FROM
(
SELECT
Categories.CategoryName,
YEAR(Orders.ShippedDate) AS ShippingYear,
CONVERT(money,([Order Details].UnitPrice*Quantity*(1-Discount)/100))*100 as Sales
FROM
Orders
INNER JOIN [Order Details] ON Orders.OrderID = [Order Details].OrderID
INNER JOIN Products ON [Order Details].ProductID = Products.ProductID
INNER JOIN Categories ON Products.CategoryID = Categories.CategoryID
WHERE (((Orders.ShippedDate) Between '19960101' And '19971231'))
) AS SourceTable
PIVOT
(
SUM(Sales)
FOR CategoryName IN ([Confections],[Meat/Poultry],
[Beverages],[Grains/Cereals],[Seafood])
) AS pvt

Resources