Select most Occurred Value SQL with Inner Join - sql

I am using this query to get the following data from different linked tables. But let's say the VENDORS for an item were three. Now here in result i want to show the Vendor which occurred most. I mean if Item ABC was supplied by 3 different vendors many times. Then here i want to get the Vendor who supplied most of the times item ABC.
My query is this.
use iBusinessFlex;
SELECT Items.Name,
Max(Items.ItemID) as ItemID ,
MAX(Items.Description)as Description,
MAX(ItemsStock.CurrentPrice) as UnitPrice,
MAX(ItemsStock.Quantity) as StockQuantiity,
MAX(Vendors.VendorName) as VendorName,
SUM(ItemReceived.Quantity) as TotalQuantity
From ItemReceived
INNER JOIN Items ON ItemReceived.ItemId=Items.ItemID
INNER JOIN ItemsStock ON ItemReceived.ItemId=ItemsStock.ItemID
INNER JOIN PurchaseInvoices ON PurchaseInvoices.PurchaseInvoiceId = ItemReceived.PurchaseInvoiceId
INNER JOIN Vendors ON Vendors.VendorId = PurchaseInvoices.VendorId
Group By Items.Name
EDIT : I have included this sub query but i am not sure if it is showing correct result. i mean Showing Vendor for each Item who provided that item most of the times
use iBusinessFlex;
SELECT Items.Name,
Max(Items.ItemID) as ItemID ,
MAX(Items.Description)as Description,MAX(ItemsStock.CurrentPrice) as UnitPrice,
MAX(ItemsStock.Quantity) as StockQuantiity,MAX(Vendors.VendorName) as VendorName,
SUM(ItemReceived.Quantity) as TotalQuantity
From ItemReceived
INNER JOIN Items ON ItemReceived.ItemId=Items.ItemID INNER JOIN ItemsStock
ON ItemReceived.ItemId=ItemsStock.ItemID INNER JOIN PurchaseInvoices
ON PurchaseInvoices.PurchaseInvoiceId = ItemReceived.PurchaseInvoiceId INNER JOIN Vendors
ON Vendors.VendorId IN (
SELECT Top 1 MAX(PurchaseInvoices.VendorId) as VendorOccur
FROM PurchaseInvoices INNER JOIN Vendors ON Vendors.VendorId=PurchaseInvoices.VendorId
GROUP BY PurchaseInvoices.VendorId
ORDER BY COUNT(*) DESC
And the Result Looks like this.

First, I would start with who ordered what thing the most. But the MOST is based on what... the most quantity? Price?, Number of Times? If you use one vendor and order 6 times qty of 10 you have 60 things. But order 1 time from another vendor for 100 qty, which one wins. You have to decide the basis of MOST, but I will go based on most times
per your original question.
So all things come from PurchasedInvoices which has a vendor ID. I dont care who the vendor is, just their ID, so no need to join. Also, don't need the item name if I am just looking for my counts. The query below will show per item, each vendor and their respective most times ordered and quantities ordered. I added the items and vendor table joins just to show the names.
select
IR.ItemID,
PI.VendorID,
max( I.Name ) Name,
max( V.VendorName ) VendorName,
count(*) as TimesOrderedFrom,
SUM( IR.Quantity ) as QuantityFromVendor
from
ItemsReceived IR
JOIN PurchaseInvoices PI
on IR.PurchaseInvoiceID = PI.PurchaseInvoiceID
JOIN Items I
on IR.ItemID = I.ItemID
JOIN Vendors V
on IR.VendorID = V.VendorID
group by
IR.ItemID,
PI.VendorID
order by
-- Per item
IR.ItemID,
-- Most count ordered
count(*),
-- If multiple vendors, same count, get total quantity
sum( IR.Quantity )
Now, to get only 1 per item, this would create a correlated subquery and you
can add 'TOP 1' to return only the first by this. Since the aggregate of count
is already done, you can then get the vendor contact info.
select
I.Name,
V.VendorName,
TopVendor.TimesOrderedFromVendor,
TopVendor.QuantityFromVendor
from
Items I
JOIN ( select TOP 1
IR.ItemID,
PI.VendorID,
count(*) as TimesOrderedFrom,
SUM( IR.Quantity ) as QuantityFromVendor
from
ItemsReceived IR
JOIN PurchaseInvoices PI
on IR.PurchaseInvoiceID = PI.PurchaseInvoiceID
where
-- correlated subquery based on the outer-most item
IR.ItemID = I.ItemID
group by
IR.ItemID,
PI.VendorID
order by
-- Per item
IR.ItemID,
-- Most count ordered
count(*),
-- If multiple vendors, same count, get total quantity
sum( IR.Quantity ) ) TopVendor
on I.ItemID = TopVendor.ItemID
JOIN Vendors V
on TopVendor.VendorID = V.VendorID
No sense in having the INNER Subquery joining on the vendor and items just for the names. Get those once and only at the end when the top vendor is selected.

Related

Get all records having count from one table is greater than sum of other table

I have three tables 1) CustomerOrders, 2) StockItems and 3) OrderContentsLine. StockItems have customerorderid (one to many relationship with CustomerOrders) and OrderContentsLine contains order items with item quantity (obviously one to many relationship with CustomerOrders).
Now I want to get All orders which have sum of quantity from OrderContentsLine table greater than count of StockItems
myquery looks like this
select co.OrderNumber,si.SalesOrderID, sum(ocl.Quantity) Ordered, count(si.SalesOrderID) Allocated from CustomerOrders co
inner join StockItems si on co.OrderID = si.SalesOrderID
inner join OrderContentsLine ocl on ocl.OrderID=co.OrderID
where co.CompanyId=531
group by si.SalesOrderID,co.OrderNumber
having count(si.SalesOrderID)>sum(ocl.Quantity)
but this query shows no results, and I am damn sure that many orders have greater order conterntline items than sum of quantity from StockItems table.
Can you please review my query and suggest the better way to get these orders!
My required output is
NOTE: this output is not generated by query !
I have just created a query that gives me the required output
select * from(
select co.OrderNumber, co.OrderID, co.OrderStatus,
(select sum(tbl.Quantity) from OrderContentsLine tbl where tbl.OrderID=co.OrderID) Ordered,
(select count(*) from StockItems tbl2 where tbl2.SalesOrderID=co.OrderID ) Allocated
from CustomerOrders co
)temp where temp.Allocated> temp.Ordered
Your problem is the multiple one-to-many joins. You are counting and summing duplicates. For example, if you have 1 order with 2 stock items, and 3 order lines, your join of the three tables will have 6 rows. You have no relationship between StockItem and OrderContentsLine, so you get a cartesian product.
You probably want something like
WITH ord AS
(
SELECT co.CompanyId, co.OrderID, co.OrderNumber, SUM(ocl.Quantity) AS Ordered
FROM CustomerOrders co
INNER JOIN OrderContentsLine ocl ON ocl.OrderID = co.OrderID
GROUP BY co.CompanyId, co.OrderNumber
), al AS
(
SELECT co.CompanyId, co.OrderID, co.OrderNumber, COUNT(si.SalesOrderID) AS Allocated
FROM CustomerOrders co
INNER JOIN StockItems si ON co.OrderID = si.SalesOrderID
GROUP BY co.CompanyId, co.OrderNumber
)
SELECT ord.CompanyId, ord.OrderNumber, ord.Ordered, al.Allocated
FROM ord
INNER JOIN al ON ord.OrderID = al.OrderID
WHERE companyId = 531
AND al.Allocated > ord.Ordered
Obviously hard to test with no data

subquery uses ungrouped column "psi.product_id" from outer query

I have the following model:
For every stock item, I'd like to know the the total ordered amount. In my model, every product is linked to one or many stock items together with an amount. And every order item is linked to a product, also with an amount.
Example: The product is "Screws Box", and it's linked to 50x stock item "Screw". A customer placed an order with 3x "Screws Box". That leads to a total of 150 ordered screws.
The query I built is the following:
SELECT
stock_item.id,
(
SELECT
SUM("amount"),
(
SELECT SUM("amount")
FROM order_item AS item
WHERE item.product_id = psi.product_id
) AS "item_amount"
FROM product_productstockitem AS psi
WHERE psi.stock_item_id = stock_item.id
) AS "product_amount"
FROM stock_stockitem AS stock_item
;
PostgreSQL tells me this:
ERROR: subquery uses ungrouped column "psi.product_id" from outer query
LINE 10: WHERE item.product_id = psi.product_id
How can this be achieved?
I think you want to join the tables together and aggregate:
select s.id,
sum(psi.amount * oi.amount)
from stock_stockitem s left join
product_productstockitem psi
on psi.stock_item_id = stock_item.id left join
order_item oi
on oi.product_id = psi.product_id
group by s.id

Aggregate after join without duplicates

Consider this query:
select
count(p.id),
count(s.id),
sum(s.price)
from
(select * from orders where <condition>) as s,
(select * from products where <condition>) as p
where
s.id = p.order;
There are, for example, 200 records in products and 100 in orders (one order can contain one or more products).
I need to join then and then:
count products (should return 200)
count orders (should return 100)
sum by one of orders field (should return sum by 100 prices)
The problem is after join p and s has same length and for 2) I can write count(distinct s.id), but for 3) I'm getting duplicates (for example, if sale has 2 products it sums price twice) so sum works on entire 200 records set, but should query only 100.
Any thoughts how to sum only distinct records from joined table but also not ruin another selects?
Example, joined table has
id sale price
0 0 4
0 0 4
1 1 3
2 2 4
2 2 4
2 2 4
So the sum(s.price) will return:
4+4+3+4+4+4=23
but I need:
4+3+4=11
If the products table is really more of an "order lines" table, then the query would make sense. You can do what you want by in several ways. Here I'm going to suggest conditional aggregation:
select count(distinct p.id), count(distinct s.id),
sum(case when seqnum = 1 then s.price end)
from (select o.* from orders o where <condition>) s join
(select p.*, row_number() over (partition by p.order order by p.order) as seqnum
from products p
where <condition>
) p
on s.id = p.order;
Normally, a table called "products" would have one row per product, with things like a description and name. A table called something like "OrderLines" or "OrderProducts" or "OrderDetails" would have the products within a given order.
You are not interested in single product records, but only in their number. So join the aggregate (one record per order) instead of the single rows:
select
count(*) as count_orders,
sum(p.cnt) as count_products,
sum(s.price)
from orders as s
join
(
select order, count(*) as cnt
from products
where <condition>
group by order
) as p on p.order = s.id
where <condition>;
Your main problem is with table design. You currently have no way of knowing the price of a product if there were no sales on it. Price should be in the product table. A product cost a certain price. Then you can count all the products of a sale and also get the total price of the sale.
Also why are you using subqueries. When you do this no indexes will be used when joining the two subqueries. If your joins are that complicated use views. In most databases they can indexed

Select SUM from multiple tables

I keep getting the wrong sum value when I join 3 tables.
Here is a pic of the ERD of the table:
(Original here: http://dl.dropbox.com/u/18794525/AUG%207%20DUMP%20STAN.png )
Here is the query:
select SUM(gpCutBody.actualQty) as cutQty , SUM(gpSewBody.quantity) as sewQty
from jobOrder
inner join gpCutHead on gpCutHead.joNum = jobOrder.joNum
inner join gpSewHead on gpSewHead.joNum = jobOrder.joNum
inner join gpCutBody on gpCutBody.gpCutID = gpCutHead.gpCutID
inner join gpSewBody on gpSewBody.gpSewID = gpSewHead.gpSewID
If you are only interested in the quantities of cuts and sews for all orders, the simplest way to do it would be like this:
select (select SUM(gpCutBody.actualQty) from gpCutBody) as cutQty,
(select SUM(gpSewBody.quantity) from gpSewBody) as sewQty
(This assumes that cuts and sews will always have associated job orders.)
If you want to see a breakdown of cuts and sews by job order, something like this might be preferable:
select joNum, SUM(actualQty) as cutQty, SUM(quantity) as sewQty
from (select joNum, actualQty, 0 as quantity
from gpCutBody
union all
select joNum, 0 as actualQty, quantity
from gpSewBody) sc
group by joNum
Mark's approach is a good one. I want to suggest the alternative of doing the group by's before the union, simply because this can be a more general approach for summing along multiple dimensions.
Your problem is that you have two dimensions that you want to sum along, and you are getting a cross product of the values in the join.
select joNum, act.quantity as ActualQty, q.quantity as Quantity
from (select joNum, sum(actualQty) as quantity
from gpCutBody
group by joNum
) act full outer join
(select joNum, sum(quantity) as quantity
from gpSewBody
group by joNum
) q
on act.joNum = q.joNum
(I have kept Mark's assumption that doing this by joNum is the desired output.)

SQL Selecting Distinct Count of items where 2 conditions are met

I am struggling to get a DISTINCT COUNT working with SQL DISTINCT SELECT
Not sure if I should even be using distinct here, but I have got it correct using a subquery, though it is very heavy processing wise.
This query does what I ultimately want results wise (without the weight)
SELECT DISTINCT
product_brandNAME,
product_classNAME,
(SELECT COUNT(productID) FROM products
WHERE products.product_classID = product_class.product_classID
AND products.product_brandID = product_brand.product_brandID) as COUNT
FROM products
JOIN product_brand
JOIN product_class
ON products.product_brandID = product_brand.product_brandID
AND products.product_classID = product_class.product_classID
GROUP BY productID
ORDER BY product_brandNAME
This gets close, and is much more efficient, but I can't get the count working, it only counts (obviously) the distinct count which is 1.
SELECT DISTINCT product_brandNAME, product_classNAME, COUNT(*) as COUNT
FROM products
JOIN product_brand
JOIN product_class
ON products.product_brandID = product_brand.product_brandID
AND products.product_classID = product_class.product_classID
GROUP BY productID
ORDER BY product_brandNAME
Any suggestions, I'm sure its small, and have been researching the net for hours for an answer to no avail for 2 conditions to match.
Thanks,
Have you tried following query
Edit
SELECT product_brandNAME
, product_classNAME
, COUNT(*)
FROM products
JOIN product_brand ON products.product_brandID = product_brand.product_brandID
JOIN product_class ON products.product_classID = product_class.product_classID
GROUP BY
product_brandNAME
, product_classNAME
When using GROUP BY you do not need to use a DISTINCT clause. Try the following:
SELECT productID,
product_brandNAME,
product_classNAME,
COUNT(*) as COUNT
FROM products JOIN product_brand ON products.product_brandID = product_brand.product_brandID
JOIN product_class ON products.product_classID = product_class.product_classID
GROUP BY productID,
product_brandNAME,
product_classNAME
ORDER BY product_brandNAME