SQL displaying the right number, names - sql

I'm working on a Coffee Shop database and trying to find number of sales per item. The number comes back correctly, but instead of displaying the name of the coffee and the sales it displays all the coffee names with the correct data of the first drink, then all of the coffee names with the correct data of the second drink.
select p.ProductName, TotalSold = SUM(o.Quantity)
From MSProducts p, MSOrderline o
Group By p.ProductName, o.ProductID
Output should be...
1 FlavoredSyrup-Shot 11
2 ExtraExpresso 7
3. Americano-Small 5
Though it didn't fit on the page it continues with the quantity 5 below.

I think the lack of join condition was the cause of data duplication. This may work, provided you have ProductID in both tables.
select p.ProductName, SUM(o.Quantity) as TotalSold
From MSProducts p
inner join MSOrderline o
on p.ProductID = o.ProductID
Group By p.ProductName

You need to map both the tables correctly.
MSProducts p, MSOrderline o
If you dont map then all the rows of first table will be mapped with all the rows of the second table. Please map it using the common column

Related

SQL Server query that both returns items with a foreign key and items that doesn't have it

I have a discount page where I can add Products that should have a discounted price.
Each product shows up with a number of Product Variants underneath it which can then be unchecked if they shouldn't be part of the discount.
When I press save each "CHECKED" ProductId and VariantId will be stored in a table called StoreDiscountRuleVariant.
If an existing discount page is opened in order to edit then my SQL query is no longer fetching the unchecked product-Variants from the ProductVariant table only the "checked" ones that were saved.
I want the SQL query to both return the ProductVariants that has a matching variantId foreign key in the StoreDiscountRuleVariant table as well as the ones that doesn't. I would also be needing an extra returned column that shows if the variantId was actually present in the StoreDiscountRuleVariant table - for instance isChecked=true/false.
I think this solution would be better than storing both the checked as well as the unchecked variantIds in the StoreDiscountRuleVariant table after saving since new ProductVariants that were added after this discount was made wouldn't show up while editing.
I was pointed in the direction of doing this:
SELECT p.productid, pv.variantnameSE, pv.sku, pv.variantId,
rv.discountrulevariantid, rv.productvariantid FROM
dbo.StoreDiscountRuleVariant rv INNER JOIN dbo.Product p ON p.productId =
rv.productid LEFT JOIN dbo.productVariant pv ON pv.foreignProductId =
p.productId WHERE rv.discountruleid = 24
Here is the result:
Row1:
productid: 1326, variantnamese: Vit, sku: FOD46-1, variant.variantid: 822, discountrulevariantid: 572, discountrulevariant.productvariantid: 1035
ROW2:
productid: 1326, variantnamese: Svart, sku: FOD46-2, variant.variantid: 1035 , discountrulevariantid: 572, discountrulevariant.productvariantid: 1035
Only ROW2/variantid: 1035 exists in StoreDiscountRuleVariant table.
So the strange thing for me at least is that discountrulevariantid points to 1035 on both of the rows. shouldn't ROW1's discountrulevariantid: value be empty since variantid:822 doesn't exist in StoreDiscountRuleVariant.
You need a LEFT JOIN. It is unclear whether you want all products or all storediscountrulevariants.
Whichever you want, that should be the first table. Based on the WHERE clause, I am assuming it the variants:
SELECT rv.productid, rv.productvariantid as variantid,
p.productnameSE as productname, pv.variantnameSE as variantname,
pv.sku, pv.ishidden, pp.picUrl, pp.picid
FROM dbo.StoreDiscountRuleVariant rv LEFT JOIN
dbo.Product p
ON p.productId = rv.productid LEFT JOIN
dbo.productVariant pv
ON pv.variantId = rv.productvariantid OUTER APPLY
(SELECT TOP (1) pp.*
FROM productpic pp
WHERE pp.productid = p.productid
ORDER BY pp.isfrontpic DESC
) pp
WHERE rv.discountruleid = 16
ORDER BY rv.productid, pv.sortOrder;
OUTER APPLY is then correct for the lateral join. CORSS APPLY -- like INNER JOIN -- would remove the unmatched variants.

PostgreSQL: sub-queries and aggregate functions(Sum)

I tried referring to other questions; I've inferred that sub-queries cannot be used on aggregate functions, but I cannot solve this use case.
Tables:
1. CustomerInfo(c_id,name)
2. ProductInfo(p_id,price)
3. ModelInfo(p_id,m_id,name)
4. PurchaseRecords(c_id,m_id,quantity)
Required output:
List of customer names, with total amount purchased by each customer.
My flow of thought is that:
Link PurchaseRecords with ModelInfo to get p_id,
ModelInfo with ProductInfo to get the price,
Multiply price returned by quantity in PurchaseRecords for every specific customer,
which requires me to link CustomerInfo in the end to get the name.
I'm using Postgres. I could write a program for that in Java, but I find it hard to do it with SQL. So, what is the correct query here? Any pointers on how to think problems out are appreciated!
SELECT
c.name as customer_name,
sum(coalesce(p.price, 0) * coalesce(pr.quantity, 0)) as amount_purchased
from
CustomerInfo c
left join PurchaseRecords pr on c.c_id = pr.c_id
left join ModelInfo mi on mi.m_id = pr.m_id
left join ProductInfo p on p.p_id = mi.p_id
group by
c.name

Access 2013 SQL, three tables, two using sum wrong results

Can someone please help me with this issue? I've scoured the Internet looking at dozens of examples, but i just can't find a solution that works.
I am using Access 2013. The problem is that I am trying to make a query that will highlight all part numbers from a supplier that either has customer back orders and/or overdue deliveries.
I am using three tables:
tbl_Inventory_Master which I require the part number, on hand stock value, and the supplier code.
For any back orders I need to join the tbl_Customer_Back_Order table as I need the count of back order lines and the sum of the back order quantity.
If the supplier has a late delivery, then I need to add the tbl_On_Order table showing the count of overdue deliveries and the sum of the overdue quantities.
The query is retrieving the data but the returned quantities are double what they should be.
SELECT
I.Inventory_Part_Num, I.Description, I.On_Hand_Stock,
COUNT (B.Part_Number) AS Back_Order_Count, SUM(B.Back_Order_Qty) as BO_Qty,
COUNT(O.Part_Number) AS Late_Deliveries_Count, SUM(O.Order_Qty) AS Late_Qty
FROM (tbl_Inventory_Master AS I
LEFT OUTER JOIN tbl_Customer_Back_Order AS B
ON I.Inventory_Part_Num = B.Part_Number)
LEFT OUTER tbl_On_Order AS O
ON I.Inventory_Part_Num = O.Part_Number
WHERE
I.Customer_Code = '274' AND
O.Due_Date < [ENTER TODAYS DATE IN FORMAT DD/MM/YYYY]
GROUP BY I.Inventory_Part_Num, I.Description, I.On_Hand_Stock
For example, for the part number 2022940 I should have 10 back order lines and an overdue quantity of 43. Instead, the query is returning 20 back order lines and an overdue quantity sum of 86.
From the on order table I have three orders totaling 144 pieces, instead the query is returning 960.
Can someone please advise, as this is driving me crazy?
You are joining along unrelated dimensions, so you need to aggregate before joining:
SELECT I.Inventory_Part_Num, I.Description, I.On_Hand_Stock,
B.Back_Order_Count, B.BO_Qty,
O.Late_Deliveries_Count, O.Late_Qty
FROM (tbl_Inventory_Master AS I LEFT OUTER JOIN
(SELECT B.Part_Number, COUNT(*) as Back_Order_Count,
SUM(B.Back_Order_Qty) as BO_Qty
FROM tbl_Customer_Back_Order AS B
GROUP BY B.Part_Number
) as B
ON I.Inventory_Part_Num = B.Part_Number
) LEFT JOIN
(SELECT O.Part_Number, COUNT(O.Part_Number) AS Late_Deliveries_Count,
SUM(O.Order_Qty) AS Late_Qty
FROM tbl_On_Order AS O
WHERE O.Due_Date < [ENTER TODAYS DATE IN FORMAT DD/MM/YYYY]
GROUP BY O.Part_Number
) as O
ON I.Inventory_Part_Num = O.Part_Number
WHERE I.Customer_Code = '274';
Notice the outer aggregation is no longer needed.

Query AND and not OR using WHERE IN (list)

Considering I have three tables:
product
shop
supplier
and their junction tables:
product_shop
product_supplier
I am trying to get all products that are supplied by a specific supplier and available in multiple shops, i.e. all products from supplier A that are in shop 1 and 2.
If we assume, supplier has 10 products, of which 5 are available in shop 1 and 7 are available in shop 2, but only 3 are available in shop 1 and 2, then those are the 3 I am seeking.
Here is what I have so far (in postgresql 9.6), which simulates an inclusive IN. Which works, but it doesn't seem right (proper) to me:
edit:
I use this query dynamically and have therefor to pass the list of shops (which varies), the supplier of course, and the count (which is equal to the length of the list of shops). It's not that this is a bother, but I was nonetheless wondering if there is a way to create a query using only joins.
SELECT
product_shop.product
FROM
(SELECT product FROM product_shop where shop in (1, 2)) product_shop JOIN
product_supplier ON product_shop.product = product_supplier.product
WHERE
product_supplier.supplier = A
GROUP BY
product_shop.product
HAVING
count(product_shop.product) = 2
Is there a better query to achieve the result I am seeking?
*Not a native speaker
I believe this will give you the desired result
SELECT product.* FROM product
JOIN product_supplier ON product.id = product_supplier.productId
JOIN product_shop ON product.id = product_shop.productId
WHERE product_shop.shopId IN (1 , 2)
AND product_supplier.supplierId = 'A'
GROUP BY product.id
HAVING COUNT(product.id) > 1
Its basically equivalent, but you do not need the subquery. There is, however, an error.
With your query you will only get the products that are available in exactly 2 shops.
since you wrote:
I am trying to get all products that are supplied by a specific supplier and available in multiple shops
Using HAVING COUNT(product.id) > 1 would be more generic and correct.
However, it would not make any difference in this case, since you restricted the search to 2 shops.
I Also changed references like product_supplier.supplier to product_supplier.supplierId. You shroud use Id fields for table relationships.
Here is the query with out Having the count
with cte_product -- fetching all the products which are in shop 1&2
(
SELECT product,count(product) as cnt FROM product_shop
where shop in (1, 2)
group by product
)
SELECT *
FROM
cte_product psh
JOIN
product_supplier psu
ON psh.product = psu.product
WHERE
psu.supplier = A
and psh.cnt > 1;

sql - calculating the price of an order and sum of all orders on a receipt

I have three tables as follows:
MenuItem
MenuItemID ItemName ItemPrice
X0001 LatteSmall $15
X0002 LatteBig $18
X0003 MochaSmall $16
Orders
OrderID MenuItemID ReceiptID`
O000001 X0001 R000001
O000002 X0002 R000001
O000003 X0001 R000002
O000004 X0003 R000003
Receipt
ReceiptID ReceiptPrice
R00000001 ???????????
R00000002 ???????????
R00000003 ???????????
R00000004 ???????????
What I am trying yo do is: Calculate the price of each order, and then sum up orders that belong to each receipt. List the summed up values in the ReceiptPrice field on the Receipt table.
How do I do this with a single query on Microsoft Access 2010?
Any help is appreciated =))
From the sample data you have provided it's a little hard to tell, but I assume that each receipt may contain multiple orders.
The following query will return each order on each receipt with a total menu item cost per order. This assumes that ItemPrice is numerical, and doesn't actually contain the '$' character, maybe you could confirm that?
SELECT O.ReceiptID, O.OrderID, SUM(MI.ItemPrice) AS TotalReceiptPrice
FROM Orders AS O INNER JOIN MenuItem AS MI ON O.MenuItemID = MI.MenuItemID
GROUP BY O.ReceiptID, O.OrderID
If you wish to only see the total for each receipt, including multiple orders, then try this;
SELECT O.ReceiptID, SUM(MI.ItemPrice) AS TotalReceiptPrice
FROM Orders AS O INNER JOIN MenuItem AS MI ON O.MenuItemID = MI.MenuItemID
GROUP BY O.ReceiptID
You want to update the database. Here is one way:
update receipt
set receiptprice = (select sum(itemprice)
from menuitem inner join
orders
on menuitem.menuitemid = orders.menuitemid
where orders.receiptid = receipt.receiptid
);