Need to join a third table for detail summing - sql

the data that is created has summary totals like Invoice Amount. Now we don't want invamt but the invamt without the freight charges. Each detail row has a part#, qty, and sale price. We need to join det_table on the otord# = idord#.
But also to sum the det_table, per order, the idprt# must not start with 'FRT' thats how we know freight. I am not sure what sort of join i think left outer.
I then need to include in the first line below, the (qty* sale_price as lintot where idprt# does not start with 'FRT') but then also sum this lintot for the order#.
CREATE VIEW CLSPAYTP AS SELECT OTCOM#, OTORD#, OTTRND, OTTRT, INVAMT,
IHORG$, IHORD$, IHINV#,
OTUSRN, OTTRNC, IHPTTC, IHSLR#, IHORDT,
IHDOCD, RFCAT, RFSLC,
RFSQ2, RFDTA
FROM AZLIB.CLSPAYTPP
WHERE
OTTRNC='001'
UNION
SELECT
OTCOM#, OTORD#, OTTRND, OTTRT, INV
INVAMT, IHORG$, IHORD$,IHINV#, OTUSRN, OTTRNC, IHPTTC,
IHSLR#, IHORDT,
IHDOCD, RFCAT, RFSLC, RFSQ2, RFDTA FROM
AZLIB.CLSPAYTPP OT1
WHERE OTTRT = (SELECT MIN(OTTRT)
FROM AZLIB.CLSPAYTPP OT2
WHERE OT2.OTTRNC<>'001' AND OT1.OTORD#= OT2.OTORD#
GROUP BY OT2.OTORD#)

Related

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.

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
);

Using the HAVING Clause with GROUP by to Return Unique Records

Good day all,
I am having difficulty understanding the mechanics of the GROUP BY AND HAVING clause and was hoping for some advice.
I am trying to query two tables - PRODUCTS and ORDER_ITEMS. The PRODUCT_ID column is used to link these two tables.
I wish to view products which have been ordered from a certain supplier (filtered using the SUPPLIER_ID column which is in ORDER_ITEMS); have been successfully ordered before (ORDER_STATUS 6 in ORDER_ITEMS);and which have not been deleted (RECORD_DELETED column in ORDER_ITEMS). I only use the PRODUCTS table to show the name of the product. Furthermore I only want distinct products returned, meaning I want to exclude any results which duplicate the PRODUCT_ID column
This is the query that I am using:
SELECT
PD.PRODUCT_ID,
PD.PRODUCT_NAME,
PD.BARCODE,
PD.SUPPLIER_BARCODE,
COUNT(PD.PRODUCT_ID) AS COUNTED,
ODI.ORDER_ITEM_ID
FROM PRODUCTS PD
INNER JOIN ORDER_ITEMS ODI
ON PD.PRODUCT_ID = ODI.PRODUCT_ID
WHERE ODI.SUPPLIER_ID = 34359738399
AND ORDER_STATUS = 6
AND ODI.RECORD_DELETED = 0
GROUP BY PD.PRODUCT_ID,PD.PRODUCT_NAME,PD.BARCODE,PD.SUPPLIER_BARCODE,ODI.ORDER_ITEM_ID
HAVING COUNT(ODI.PRODUCT_ID) = 1
ORDER BY PRODUCT_ID ASC
Unfortunately this is returning 502 records with many of them duplicating the PRODUCT_ID. If I remove the ORDER_ITEM_ID column from the query 175 records are returned. These 175 records are products that meet the criteria given above. The problem is that I also need to pull the ORDER_ITEM_ID from ORDER_ITEMS (along with some other columns).
I vaguely understand that when I include ORDER_ITEMS the query is going to group the data by the ORDER_ITEM column and so will count the PRODUCT_ID values based on each individual ORDER_ITEM_ID. This results in there always being a count of 1 for each product.
How does one get around this? Also, is there a more suitable way of carrying out this task which would allow me to include one ORDER_ITEM record for every duplicated product? Rather than omitting them altogether as I am doing above?
This is some of the data that is returned by the query above:
PRODUCT_ID,PRODUCT_NAME,BARCODE,SUPPLIER_BARCODE,COUNTED,ORDER_ITEM_ID
34359738628,ADCORTYL INTRA-ARTIC/DERMAL 10MG/ML 5ML,5099627022132,5012712000037,1,34359755708
34359739609,ARTELAC 3.2MG/ML EYE DROPS SOLN,5099627456722,5027519008933,1,34359741719
34359739626,ASACOLON 500MG SUPPOSITORIES,5099627516587,5015313012737,1,34359742783
34359739767,ATROVENT 250MCG/1ML UDV NEB SOLN,5099627639637,5012816012561,1,34359738421
34359739770,ATROVENT 500MCG/2ML UDV NEB SOLN,5099627460293,5012816012592,1,34359743524
34359739893,AZOPT 10MG/ML EYE DROPS SUSP,5099627831543,5015664002753,1,34359749091
34359739893,AZOPT 10MG/ML EYE DROPS SUSP,5099627831543,5015664002753,1,34359749687
34359739893,AZOPT 10MG/ML EYE DROPS SUSP,5099627831543,5015664002753,1,34359749715
34359739893,AZOPT 10MG/ML EYE DROPS SUSP,5099627831543,5015664002753,1,34359754053
34359740053,BACTIGRAS MED DRSS 10CMX10CM STERILE GMS,5099627672368,5000223421984,1,34359748101
34359740062,BACTROBAN 2% OINTMENT,5099627053914,5099211003165,1,34359755226
34359740558,BETNOVATE RD CREAM,5099627005692,5099211001642,1,34359752422
34359740558,BETNOVATE RD CREAM,5099627005692,5099211001642,1,34359738487
34359741045,BISODOL ANTACID TABS,5099627057707,5014398001438,1,34359750542
34359741995,BROLENE 0.1% EYE DROPS SOLN,5099627006323,50982790,1,34359746555
34359741995,BROLENE 0.1% EYE DROPS SOLN,5099627006323,50982790,1,34359751650
34359741995,BROLENE 0.1% EYE DROPS SOLN,5099627006323,50982790,1,34359751783
34359742132,BURINEX 1MG TABS,5099627551328,5702191004212,1,34359749705
34359742152,BUSCOPAN 20MG/ML SOLN FOR INJ,5099627006620,5012816018532,1,34359749083
In the example above, several records were returned with duplicate PRODUCT_ID values e.g ASACOLON 500MG SUPPOSITORIES
You need GROUP_CONCAT/LISTAGG equivalent in SQL Server. You can use XML, STUFF and correlated subquery as replacement.
If PRODUCT_ID is UNIQUE you can use:
WITH cte AS
(
SELECT
PD.PRODUCT_ID,
PD.PRODUCT_NAME,
PD.BARCODE,
PD.SUPPLIER_BARCODE,
ODI.ORDER_ITEM_ID
FROM PRODUCTS PD
JOIN ORDER_ITEMS ODI
ON PD.PRODUCT_ID = ODI.PRODUCT_ID
WHERE ODI.SUPPLIER_ID = 34359738399
AND ORDER_STATUS = 6
AND ODI.RECORD_DELETED = 0
)
SELECT PRODUCT_ID,
PRODUCT_NAME,
BARCODE,
SUPPLIER_BARCODE,
[COUNTED] = COUNT(PD.PRODUCT_ID),
[ORDER_ITEM_ID] = STUFF((SELECT CONCAT(',' , ORDER_ITEM_ID)
FROM cte c2
WHERE c2.PRODUCT_ID = c1.PRODUCT_ID
ORDER BY c2.ORDER_ITEM_ID
FOR XML PATH ('')), 1, 1, '')
FROM cte c1
GROUP BY PRODUCT_ID,PRODUCT_NAME,BARCODE,SUPPLIER_BARCODE
HAVING COUNT(PRODUCT_ID) = 1
ORDER BY PRODUCT_ID ASC;
LiveDemo_SimplifiedVersion
Otherwise correlate using multiple columns:
SELECT CONCAT(',' , ORDER_ITEM_ID)
FROM cte c2
WHERE c2.PRODUCT_ID = c1.PRODUCT_ID
AND c2.PRODUCT_NAME = c1.PRODUCT_NAME
AND ...
ORDER BY c2.ORDER_ITEM_ID
FOR XML PATH ('')), 1, 1, '')

SQL query to report on what invoices have not been paid, ordered by invoice number

new to SQL and only been doing it for a week and a half. So I apologise now for the question being simple or appearing to be stupid.
I want to present a report on invoices that have not been paid by a given date, ordered by invoice number.
This is how I have displayed, the paid invoices but without the given date.. How do I display, the invoices that have not been paid by say 31-MAR-14.
SELECT INVOICE.INVOICE_NUMBER, INVOICE.INVOICE_DATE, PAYMENT.PAYMENT_NO, PAYMENT.INVOICE_NUMBER
FROM INVOICE, PAYMENT
WHERE INVOICE.INVOICE_NUMBER = PAYMENT.INVOICE_NUMBER
ORDER BY INVOICE.INVOICE_NUMBER;
SELECT PAYMENT.PAYMENT_NO
FROM INVOICE, PAYMENT
WHERE INVOICE.INVOICE_NUMBER = PAYMENT.INVOICE_NUMBER
AND INVOICE.INVOICE_DATE = 'AAAAMMJJ'
ORDER BY INVOICE.INVOICE_NUMBER;
Try something like this.
I have question. How do you say the invoice are not paid ?
You need to join the two tables together with a LEFT JOIN, then look to see where the payment date is > 31-MAR-14. Try something like this:
SELECT INVOICE.INVOICE_NUMBER, INVOICE.INVOICE_DATE, PAYMENT.PAYMENT_NO, PAYMENT.INVOICE_NUMBER
FROM INVOICE
LEFT JOIN PAYMENT ON INVOICE.INVOICE_NUMBER = PAYMENT.INVOICE_NUMBER
WHERE PAYMENT.Date_of_payment > '3/31/2014'
ORDER BY INVOICE.INVOICE_NUMBER;
This looks for all payments that were made after 3/31/2014. You may need to add another condition, that limits what invoices you're looking for.
To check payments that have not been made, look where any field in the PAYMENT table is null. SQL like this:
SELECT INVOICE.INVOICE_NUMBER, INVOICE.INVOICE_DATE, PAYMENT.PAYMENT_NO, PAYMENT.INVOICE_NUMBER
FROM INVOICE
LEFT JOIN PAYMENT ON INVOICE.INVOICE_NUMBER = PAYMENT.INVOICE_NUMBER
WHERE INVOICE.INVOICE_DATE = '3/31/2014'
AND PAYMENT.PAYMENT_NO IS NULL
ORDER BY INVOICE.INVOICE_NUMBER;
LEFT JOIN in this case will always return values for the INVOICE table, but may return NULL values in place of the PAYMENT if a payment has not been entered yet. Checking AND PAYMENT.PAYMENT_NO IS NULL will tell you that a payment has not been made yet.

Total price from different tables

I have a database with customers, items and orders. This is an exam project, so is maybe not the best for real life. I have this problem. I want a list of what all our customers have bought and a total price of that, but I can't get anything to work.
select Kunder.navn,Ordre.*, Indeholder.antal, Varer.*
from Kunder
join Ordre on Kunder.kunde_nr=Ordre.kunde_nr
join Indeholder on Ordre.ordre_nr=Indeholder.ordre_nr
join Varer on Varer.vare_nr=Indeholder.vare_nr
where er_industri=0
order by bestillingsdato
I have tried a lot like:
sum (Indeholder.antal * Varer.privat_pris) as total
group by Ordre.ordre_nr
But I just can't get anything that I've tried, to give me what I'm looking for.
I hope that you want to help me, and that you understand what I mean (I'm not a native english speaker).
I have uploaded an image of our mapping, so you can see what our database look like:
And for clarity, just a translation:
Kunder = customers
Varer = items
Ordre = orders
Indeholder = includes
Just add more columns on your group by clause.
Apart from the aggregate functions [SUM(), COUNT(), AGV()] the same list of columns must be present at the group by clause
and at select clause:
So, generally:
select <col1, col2, col3...>, SUM(...)
from ...
group by <col1, col2, col3...>
If you want a per customer AND order groupping:
select Kunder.navn, Ordre.ordre_nr, sum (Indeholder.antal * Varer.privat_pris) as total
from Kunder
join Ordre on Kunder.kunde_nr=Ordre.kunde_nr
join Indeholder on Ordre.ordre_nr=Indeholder.ordre_nr
join Varer on Varer.vare_nr=Indeholder.vare_nr
where er_industri=0
group by Kunder.navn, Ordre.ordre_nr
You could also do a per customer groupping:
select Kunder.navn, sum (Indeholder.antal * Varer.privat_pris) as total
from Kunder
join Ordre on Kunder.kunde_nr=Ordre.kunde_nr
join Indeholder on Ordre.ordre_nr=Indeholder.ordre_nr
join Varer on Varer.vare_nr=Indeholder.vare_nr
where er_industri=0
group by Kunder.navn