I have three tables
tbl_worker
City WorkerName Job
10 Raymond Carpenter
10 Sara Programmer
11 John Painter
11 Alice Booker
tbl_workshop
City WorkshopName
10 Dell
11 Apple
10 Sony
Tbl_city
Id Name
10 Mexico
11 Sydney
Now I want such a result:
City WorkersQty WorkshopQry
Mexico 2 2
Sydney 2 1
The result returns the quantity of workers and workshops which are registered in different cities.
what query should I write?
Group the tbl_workshop and tbl_worker tables individually, then use a LEFT JOIN to get the results:
SELECT c.City,
k.Cnt AS WorkersQty,
w.Cnt AS WorkshopQry
FROM Tbl_city c
LEFT JOIN (
SELECT City, COUNT(*) Cnt
FROM tbl_worker
GROUP BY City
) k ON c.ID = k.City
LEFT JOIN (
SELECT City, COUNT(*) Cnt
FROM tbl_workshop
GROUP BY City
) w ON c.ID = w.City
If you want to only show the cities that have workshop's or workers, add:
WHERE k.Cnt > 0 OR w.Cnt > 0
Use Dense_rank to get the number of workshops or workers
SELECT city, MAX(WorkshopQty) AS WorkshopQty , MAX(WorkersQty) AS WorkersQty
FROM (
SELECT c.name AS City,
DENSE_RANK() OVER (PARTITION BY c.id ORDER BY WorkshopName) AS WorkshopQty,
DENSE_RANK() OVER (PARTITION BY c.id ORDER BY WorkerName) AS WorkersQty
FROM tbl_city c
INNER JOIN tbl_workshop s ON s.city = c.id
INNER JOIN tbl_worker w ON w.city = c.id
) s
GROUP BY City
Related
I have the following tables:
Customers
ID Name
============
1 John
2 Alice
3 Bob
Orders
ID CustomerID Status
==========================
1001 1 1
1002 2 1
1003 2 2
1004 3 2
I'd like to join tables showing one entry per customer only (the one with lowest Status) i.e.
ID Name OrderID
======================
1 John 1001
2 Alice 1002
3 Bob 1004
Thanks to the answer to this question, I chose 2 solutions which produce the same output:
Solution 1
SELECT c.id, c.name, o.id FROM customers AS c
INNER JOIN orders AS o ON
c.id = o.customerid
WHERE o.status = (SELECT MIN(status) FROM orders WHERE customerid = c.id)
Solution 2
SELECT c.id, c.name, o.id FROM customers as c
INNER JOIN orders AS o ON
o.id = (SELECT TOP 1 id FROM orders WHERE customerid = c.id ORDER BY status)
Trying to understand which one runs faster, I used SQL Fiddle View Execution Plan which gave the following:
Solution 1
Solution 2
How to interpret those diagrams and which one performs faster?
Using MS SQL Server 2016.
Here's my breakdown and the last one is my suggestion to you.
Query Cost 67%
SELECT c.id, c.name, o.id FROM #Customers AS c
INNER JOIN #Orders AS o ON
c.id = o.customerid
WHERE o.status = (SELECT MIN(status) FROM #Orders WHERE customerid = c.id)
Query Cost 66%
SELECT c.id, c.name, o.id FROM #Customers as c
INNER JOIN #Orders AS o ON
o.id = (SELECT TOP 1 id FROM #Orders WHERE customerid = c.id ORDER BY status)
Query Cost 47%
SELECT
x.CustID,
x.Name,
x.OrderID
FROM (SELECT
C.id CustID,
c.Name,
o.ID OrderID,
o.status,
ROW_NUMBER() OVER (PARTITION BY c.id ORDER BY o.status) rn
FROM #Customers c
INNER JOIN #Orders o
ON o.CustomerID = c.ID) x
WHERE x.rn = 1
I have to find the city where each product sold best.
I feel I am pretty close but am stumped on what to try next. I've been working on this assignment for about 8 hours now (not even an exaggeration).
There are these tables:
Tb_Product (prod_id, name, MU)
Tb_Supplier (supp_id, name, city)
Tb_Consumer (con_id, name, city)
Tb_Requests (quantity, prod_id, price, con_id)
Tb_Offers (quantity, prod_id, price, supp_id)
Tb_Transactions (quantity, price, prod_id, supp_id, con_id, tran_id)
I have the following so far:
SELECT DISTINCT Tb_Product.Name, Tb_Supplier.City, SUM(Quantity) AS 'Quantity Sold'
FROM Tb_Supplier, Tb_Transactions, Tb_Consumer, Tb_Product
WHERE Tb_Supplier.Supp_ID = Tb_Transactions.Supp_ID
AND Tb_Product.Prod_ID = Tb_Transactions.Prod_ID
GROUP BY Tb_Product.Name, Tb_Supplier.Supp_ID, Quantity, Tb_supplier.City
HAVING SUM(Quantity) >= ALL(SELECT SUM(Quantity)
FROM Tb_Supplier, Tb_Transactions
WHERE Tb_Transactions.Supp_ID=Tb_Supplier.Supp_ID
GROUP BY Quantity)
and the output I get is like this:
Name City Quantity Sold
------------------------------ ------------------------------ ----------------------
Airplane Madison 3900000
Auto Madison 3900000
Computer Madison 3900000
Milk Madison 3900000
Oil Madison 3900000
Orange Madison 3900000
Truck Madison 3900000
TV Madison 3900000
Clearly the quantity sold isn't correct and I believe it has to do with the SUM(Quantity) up top but just can't figure out what to change.
In this case JOIN is very useful than WHERE
SELECT p.Name, s.City, SUM(t.Quantity) AS 'Quantity Sold'
FROM Tb_Supplier s
JOIN Tb_Transactions t ON t.Supp_ID = s.Supp_ID
JOIN Tb_Consumer c ON c.con_id = t.con_id -- I think you forgot this condition
JOIN Tb_Product p ON p.Prod_ID = t.Prod_ID
GROUP BY p.Name, s.Supp_ID, s.City
HAVING SUM(t.Quantity) >= ALL(
SELECT SUM(Quantity)
FROM Tb_Transactions
GROUP BY Supp_ID,prod_id -- check it
)
And I think that Quantity isn't necessary in GROUP BY
GROUP BY Tb_Product.Name, Tb_Supplier.Supp_ID, /*Quantity,*/ Tb_supplier.City
Try the following query
SELECT
p.name,
d.city,
d.QSold
FROM
(
SELECT t.prod_id,s.city,SUM(t.Quantity) QSold
FROM Tb_Transactions t
JOIN Tb_Supplier s ON s.supp_id=t.supp_id
GROUP BY t.prod_id,s.city
) d
JOIN
(
SELECT prod_id,MAX(QSold) MaxQSold
FROM
(
SELECT t.prod_id,s.city,SUM(t.Quantity) QSold
FROM Tb_Transactions t
JOIN Tb_Supplier s ON s.supp_id=t.supp_id
GROUP BY t.prod_id,s.city
) d
GROUP BY prod_id
) m
ON d.prod_id=m.prod_id AND d.QSold=m.MaxQSold
JOIN Tb_Product p ON d.prod_id=p.prod_id
Or this query if your version of SQLServer supports window-functions
SELECT name,city,QSold
FROM
(
SELECT t.prod_id,p.name,s.city,SUM(t.Quantity) QSold,
MAX(SUM(t.Quantity))OVER(PARTITION BY t.prod_id) MaxQSold
FROM Tb_Transactions t
JOIN Tb_Supplier s ON s.supp_id=t.supp_id
JOIN Tb_Product p ON t.prod_id=p.prod_id
GROUP BY t.prod_id,p.name,s.city
) q
WHERE QSold=MaxQSold
"City where each product has been sold" refers to the city of consumption, so you need to join transactions to consumers, sum the quantity by that city and the product. To arrive at "the most" we need a ranking so dense_rank() can ordered by the sum of quantity (descending) and a rank of 1 would equate to "the most sold" (note: equal 1st position is allowed by using dense_rank()).
SELECT
d.city
, p.name
, d.sum_qty
FROM (
SELECT
c.city
, SUM(t.quantity) sum_qty
, t.prod_id
, DENSE_RANK() OVER (PARTITION BY c.city, t.prod_id ORDER BY SUM(t.quantity) DESC) rnk
FROM Tb_Transactions t
JOIN Tb_Consumer c ON t.con_id = c.con_id
) d
JOIN Tb_Product p ON d.Prod_ID = p.Prod_ID
WHERE d.rnk = 1
ORDER BY
d.city
, p.name
Joining the subquery result to product table reduces the rows involved in that join.
nb: using dense_rank also allows for "top n per" result, e.g. changing the where clause to where rnk <= 5 would list top 5 selling products per city.
How to get department wise highest salary and highest salary holder Employee name,consider 3 tables are joined using keys
io/-
emptable, saltable,depttable
id name dept_id id sal dept_id dept_name
1 ram 10 1 100 10 xyz
2 sham 10 2 500 20 abc
3 jadu 20 3 900 30 por
4 john 20 4 999 40 stu
5 Madhu 30 5 300 50 xxx
o/p-
name,sal,dept_name
sham 500 abc
john 999 stu
Madhu300 xxx
SELECT DISTINCT
MAX(amount) OVER (PARTITION BY d.id ORDER BY s.amount DESC) AS sal,
FIRST_VALUE(e.name) OVER (PARTITION BY d.id ORDER BY s.amount DESC) AS emp,
d.name as dept
FROM emptable e
INNER JOIN depttable d
ON e.dept_id = d.id
INNER JOIN saltable s
ON s.id = e.id
I made some assumptions for column names in your tables. You can find my schema script here.
You can JOIN all the table and then use window function row_number to choose top two records per department:
select *
from (
select t.*,
row_number() over (
partition by dept_id order by salary desc
) rn
from (
select e.*,
s.salaray,
d.dept_name
from emptable e
join saltable s on e.emp_id = s.emp_id
join depttable d on d.dept_id = e.dept_id
) t
) t
where rn <= 2;
Your table are missing the column names. So, I assumed the names (hopefully correctly)
How can I write a SQL statement to select distinct data from three tables?
There are three tables
1)
Registration
id name contact
123 abc 123456789
2) bookingReg
PkBkID FkRegID ac_no
1 123 QT123
3) products
PkPro FkBkID pro_name Qty price
1 1 abc 2 150
2 1 def 1 400
3 1 ghi 5 500
4 1 abc 2 150
SELECT * FROM Registration as a
JOIN bookingReg as b ON (b.FkRegID = '123')
JOIN products as c ON (c.FkBkID = b.PkBkID )
I want distinct pro_name
Out put is
ac_no qty price
QT123 8 1050
HOw ?
Answer based on my assumption
SELECT pro_name,
ac_no,
SUM(qty) Sumqty,
SUM(price) SumPrice
FROM Registration a
JOIN bookingReg b
ON b.FkRegID = a.id
JOIN products c
ON c.FkBkID = b.PkBkID
GROUP BY pro_name, ac_no
EDIT Remove ac_no from SELECT and GROUP BY if you don't want to see this field in result.
Pls try this
SELECT A.ac_no, SUM(A.Qty) Qty, SUM(A.Price) Price
FROM
(
SELECT DISTINCT B.ac_no, P.Qty, P.Price
FROM Registration R
INNER JOIN bookingReg B ON B.FkRegID = R.id
INNER JOIN products P ON P.FkBkID = B.PkBkID
) A
GROUP BY A.ac_no
How do I get top 1 record for each product from the query below?
SELECT DISTINCT o.product, o.orderID, od.qty, od.amount FROM
orders o, orderdetails od WHERE o.orderID=od.orderID
Product OrderID Qty Amount
Pen 11222 10 100.00
Pen 11223 5 50.00
Pen 11224 1 10.00
Book 22222 1 12.00
Book 2223 5 10.00
Scale 1111 2 9.00
Scale 2222 1 2.00
SELECT
o.Product, MAX(od.QTy)
FROM
orders o
INNER JOIN orderdetails od ON o.orderID=od.orderID
GROUP BY o.Product
or
SELECT
o.Product, MAX(od.Amount)
FROM
orders o
INNER JOIN orderdetails od ON o.orderID=od.orderID
GROUP BY o.Product
depending on what you consider as "top" product.
Top based on what? Most Quantity? if so try this
Select * From Orders O
Where OrderId =
(Select Max(orderId) From Orders
Where product = P.product
And Qty = (Select Max(Qty)
From orders
Where Product = O.Product))
Otherwise if Top means something else change last three lines to find Orderid for the record that satisfies whatever that definition of 'Top'
Give this a shot...
Select o.product, o.orderID, od.qty, od.amount
from orders o, orderdetails od
where o.orderID = od.orderID
and o.orderID in (Select Min(o.orderId)
From orders o
Group By o.product)