Access Cross tab Query - sql

I have two tables.
I need to subtract the the number of items ordered from the quantity currently
recorded.
I can get the count() of the sales of each individual item like so:
SELECT SALES.PRODUCT_ID AS ORDERED_ID
,COUNT(SALES.PRODUCT_ID) AS ORDERED
FROM SALES
GROUP BY SALES.PRODUCT_ID
Which gives me:
ORDERED_ID ORDERED
1201 2
1202 2
1204 2
1205 3
1206 1
1207 2
1208 1
1209 1
1210 3
Getting the quantity is just a matter of
SELECT PRODUCT.PRODUCT_ID AS INVEN_ID
,PRODUCT.QUANTITY AS INVEN
FROM PRODUCT
Which gives me:
INVEN_ID INVEN
1199 5
1200 2
1201 33
1202 44
1203 55
1204 66
1205 77
1206 88
1207 99
1208 110
1209 121
1210 132
I've spent hours on this problem and gave up at what I thought should be the solution:
SELECT SUB1.INVEN - SUB2.ORDERED
FROM
(SELECT PRODUCT.PRODUCT_ID AS INVEN_ID
,PRODUCT.QUANTITY AS INVEN
FROM PRODUCT
)AS SUB1
,(SELECT SALES.PRODUCT_ID AS ORDERED_ID
,COUNT(SALES.PRODUCT_ID) AS ORDERED
FROM SALES
GROUP BY SALES.PRODUCT_ID
)AS SUB2
INNER JOIN SUB1 ON SUB1.INVEN_ID = SUB2.ORDERED_ID
However, access does not recognize that last join as a valid join and without it I just get a Cartesian product. If I try to retrieve quantity without a sub query and just try to SELECT product.quantity - SUB2.ORDERED access demands that I put product.quantity - SUB2.ORDERED in an aggregate function. When I do what it says it then tells me that product.quantity - SUB2.ORDERED can't be in an aggregate function. I'm at a loss.
EDIT:
Final Solution:
SELECT SUB1.INVEN_ID AS PRODUCT_ID
,SUB1.PRODUCT_NAME AS PRODUCT_NAME
,SUB1.PRICE AS PRICE
,SUB1.INVEN - NZ(SUB2.ORDERED,0) AS AVAILABLE
FROM
(SELECT PRODUCT.PRODUCT_ID AS INVEN_ID
,PRODUCT.PRODUCT_NAME AS PRODUCT_NAME
,PRODUCT.PRICE AS PRICE
,PRODUCT.QUANTITY AS INVEN
FROM PRODUCT
)AS SUB1
LEFT JOIN
(SELECT SALES.PRODUCT_ID AS ORDERED_ID
,COUNT(SALES.PRODUCT_ID) AS ORDERED
FROM SALES
GROUP BY SALES.PRODUCT_ID
)AS SUB2 ON SUB1.INVEN_ID = SUB2.ORDERED_ID

Your INNER JOIN should put after first subquery.
I think you are looking for LEFT JOIN,because PRODUCT table should be the master table.
if you use LEFT JOIN SUB2.ORDERED column might be NULL so use NZ function
Or IIF(ISNULL(SUB2.ORDERED),0,SUB2.ORDERED) to check.
You can try this.
SELECT SUB1.INVEN - NZ(SUB2.ORDERED,0)
FROM
(SELECT PRODUCT.PRODUCT_ID AS INVEN_ID
,PRODUCT.QUANTITY AS INVEN
FROM PRODUCT
)AS SUB1
LEFT JOIN
(SELECT SALES.PRODUCT_ID AS ORDERED_ID
,COUNT(SALES.PRODUCT_ID) AS ORDERED
FROM SALES
GROUP BY SALES.PRODUCT_ID
)AS SUB2 ON SUB1.INVEN_ID = SUB2.ORDERED_ID

Related

MAX and SUM function with JOINING tables

I have two tables which is CustomerOrder and Customers
CustomerOrder
CusOrderID CusID OrderTotalPrice
S01 C01 180
S02 C04 50
S03 C05 70
S04 C07 46
S05 C09 78
S05 C09 164
Customers
CusID CusName
C01 James
C02 Jabrial
C03 Maxi
C04 Lim
C05 Tan
C06 Rem
C07 Subaru
C08 Jay
C09 Felix
I would need an output which is the customer who spent most on buying books where the display would look like this
CusID Name OrderTotalPrice
C09 Felix 242
I need to use max and sum function and join those two table together and display only one Customer which spend the most. How can I write the query ?
this below is my sample query which doesn't really work
it's Microsoft SQL and TOP function is also not encouraged.
SELECT MAX(s.Sum_OrdTotalPrice) AS max
From (SELECT CO.CusID,C.CusName,SUM(CO.OrderTotalPrice) AS Sum_OrdTotalPrice
FROM CustomerOrder CO
INNER JOIN Customers C On CO.CusID = C.CusID
Group by CO.CusID,C.CusName
)s
Order the results and take just the first row?
SELECT TOP (1) WITH TIES
CO.CusID,C.CusName,SUM(CO.OrderTotalPrice) AS Sum_OrdTotalPrice
FROM CustomerOrder CO
INNER JOIN Customers C On CO.CusID = C.CusID
GROUP BY CO.CusID,C.CusName
ORDER BY SUM(CO.OrderTotalPrice) DESC
EDIT 1: Changed to SQL Server Syntax, following edit to question
EDIT 2: Added WITH TIES so that multiple rows are returned if multiple customers are tied for highest spend
Should pretty much yield the same results a MatBailie, including ties, but avoids using TOP if that is an absolute necessity
SELECT
Results.CusID, Results.Name, Results.OrderTotalPrice
FROM (
SELECT
CustomerOrder.CusID, Customers.CusName as Name
, SUM(CustomerOrder.OrderTotalPrice) as OrderTotalPrice
, RANK() OVER (ORDER BY SUM(CustomerOrder.OrderTotalPrice) DESC) as SalesRank
FROM CustomerOrder
JOIN Customers ON Customers.CusID = CustomerOrder.CusID
GROUP BY CustomerOrder.CusID, CusName
) Results
WHERE Results.SalesRank = 1

how to calculate Sum for two different table with different containing table field

I have two table "tbl_In_Details" and "tbl_Out_Details"
Sample data for tbl_In_Details
ID Item_Name Rate Quantity Source_company
1 wire 10 4 2020-04-21 22:47:29.083
2 Tea 4 20 2020-04-21 22:47:52.823
Sample data for tbl_Out_Details
ID Item_Name Quantity Created_Date
1 wire 1 2020-04-21 22:48:48.233
2 wire 2 2020-04-21 22:50:16.367
3 Tea 2 2020-04-21 23:48:39.943
Now i want to calculate SUM of price and price (RATE*QUANTITY) from out going table
i tried in such a way but not getting result
select o.Item_Name, SUM(o.quantity) as Total_quantity ,SUM(o.quantity * i.Rate) as Expenses
from tbl_In_Details i inner join tbl_Out_Details o
ON i.Item_Name = o.Item_Name group by o.Item_Name,o.quantity, i.Rate
My Output should be
Item_Name Total_quantity Expenses
Tea 2 8
wire 3 30
Your query is completely fine. The only thing you need to get the desired result is to delete grouping by 'quantity' and 'rate'.
select o.Item_Name, SUM(o.quantity) as Total_quantity ,SUM(o.quantity * i.Rate) as Expenses
from tbl_In_Details i inner join tbl_Out_Details o
ON i.Item_Name = o.Item_Name group by o.Item_Name;
One method uses union all and group by:
Aggregate before joining:
select i.item_name, o.quantity, i.expenses
from (select id, item_name, sum(rate*quantity) as expenses
from tbl_In_Details
group by id, item_name
) i join
(select id, item_name, sum(quantity) as quantity
from tbl_Out_Details
group by id, item_name
) o
on i.id = o.id

Counting the amount of relations to one table to another

Very hard to create a good title for this.
Given the table products
productID
---------
892
583
388
And the table purchases
customerID productID
---------- ---------
56 892
97 388
56 583
56 388
97 583
How would I go about getting a table of all the costumers that have bought all products?
You can use group by and having:
select customerId
from purchases
group by customerId
having count(distinct productID) = (select count(*) from products);
Use GROUP BY clause with HAVING :
SELECT pr.customerID
FROM products p INNER JOIN
purchases pr
on pr.productID = p.productID
GROUP BY pr.customerID
HAVING COUNT(DISTINCT pr.productID) = (SELECT COUNT(*) FROM products);

Use table with multiple rows with the same value

I'm trying to do a INNER JOIN and count values with information from two tables. The problem is that the product category table have multiple rows with the same or similar value and my COUNT() is to high as a result.
My two tables
Sales table
Date prod_id
2016-01-01 81
2016-01-01 82
2016-01-01 81
2016-10-01 80
2016-01-01 80
2016-01-02 80
2016-01-02 80
2016-01-02 81
2016-01-02 81
.... ....
Product table
prodid Name
80 Banana
81 Apple
82 Orange
83 Ice Cream
80 BANANAS
81 APPLE
82
83 Ice Cream
.... ....
When I do an INNER JOIN and count the number of occurrences of e.g. prod_id I get an unreasonable high number, and my guess is that it's because there are more than one occurrence of prod_id 80 for example.
Do you have any idea for a solution? My first reaction was to redo the Procuct table, but there are many other systems depending on that table so I can't change it a foreseeable future.
My query so far:
SELECT
pt.Date AS "Date",
ft.Name AS "Product",
COUNT(ft.Name) Number
FROM SALES as pt
INNER JOIN PROD_TABLE AS ft ON pt.prod_id=ft.prodid
WHERE pt.Date BETWEEN '2016-01-01' AND '2016-01-30'
GROUP BY pt.Date, ft.Name
ORDER BY pt.Date DESC
Expected result:
Date Product Number
2016-01-01 Banana 2
2016-01-01 Apple 2
2016-01-01 Orange 1
First, you should fix the data. Having a product table with duplicates seems non-sensical. You shouldn't try to get around such issues by writing more complex queries.
That said, this is pretty easy to do in SQL Server. I think outer apply is appropriate:
select p.name, count(*)
from sales s outer apply (
(select top 1 p.*
from product p
where p.name is not null and
p.prodid = s.prod_id -- note: the columns should have the same name
) p;
I guess this simple query solves your requirement:
select
date,
name,
count(name)
from product p inner join sales s
on s.prod_id=p.prodid group by date,name

Adding duplicate values in sql

I'm just a newbie in programming and I'm having a problem with this (see table below).
DocNum DocDate Quantity ItemGroupCode ItemGroupName
89226 7-Nov-12 10 103 Fish-Fillet
88768 8-Nov-12 1 104 Fish-Regular
88856 6-Nov-12 2 104 Fish-Regular
88678 20-Nov-12 12 109 Value Added
89415 5-Nov-12 12 109 Value Added
88642 5-Nov-12 1 112 Other Charges
88646 5-Nov-12 20 112 Other Charges
88729 7-Nov-12 5.64 112 Other Charges
88804 12-Nov-12 10 112 Other Charges
88992 12-Nov-12 1 112 Other Charges
I want to combine similar Code of ItemGroupCode column then Add its Quantity.
EX.
Quantity ItemGroupCode ItemGroupName
10 103 Fish-Fillet
3 104 Fish-Regular
24 109 Value Added
38.64 112 Other Charges
Thanks ...
Pipay
Try this:
select sum(quantity) quantity, itemgroupcode, itemgroupname
from table_name
group by itemgroupcode, itemgroupname
For your question if I understand correctly, you need from the select you provide in your comments, to have the output of the first question. If this is the case then try something like this:
SELECT SUM(quantity), ItemGroupCode, ItemClass
FROM
(SELECT A.DocNum, A.DocDate, B.Quantity,B.Price,B.Linetotal, A.Doctotal, C.ItemName, C.ItmsGrpCod as ItemGroupCode,
D.ItmsGrpnam as ItemClass
FROM OINV as A LEFT outer JOIN INV1 As B ON A.DocEntry = B.DocEntry
LEFT OUTER JOIN OITM As C ON B.ItemCode = C.ItemCode
LEFT OUTER JOIN OITB As D ON C.ItmsGrpCod = D.ItmsGrpCod
WHERE A.DocDate >= '11/01/2012'
group by A.DocNum, A.DocDate, B.Quantity,B.Price,B.Linetotal, A.Doctotal, C.ItemName, C.ItmsGrpCod, D.ItmsGrpnam
order by C.ItmsGrpCod ASC) X
GROUP BY X.ItemGroupCode, X.ItemClass