Aggregation and joining 2 tables or Sub Queries - sql

I have the following tables.
Order_table
Order_ID
Item_ID
Qty_shipped
1111
11
4
1111
22
6
1111
33
6
1111
44
6
Shipping_det
Order_ID
Ship_num
Ship_cost
1111
1
16.84
1111
2
16.60
1111
3
16.60
I want my output to be as follows,
Order ID
Qty_shipped
Ship_cost
1111
22
50.04
I wrote the following query,
select sum(O.qty_shipped) as Qty_shipped, sum(S.Ship_cost) as Total_cost
from Order_table O
join shipping_det S on O.Order_ID = S.Order_ID
and I got my output as
Qty_shipped
Total_cost
66
200.16
As per my understanding, because I joined the two tables, Qty_shipped got multipled 3 times and Total_cost got multiplied 4 times.
Any help would be appreciated.
Thanks in advance.

You need to aggregate before joining. Or, to union the table together and then aggregate:
select order_id, sum(qty_shipped), sum(ship_cost)
from ((select order_id, qty_shipped, 0 as ship_cost
from order_table
) union all
(select order_id, 0, ship_cost
from shipping_det
)
) os
group by order_id;

Related

How to add a query to a table in SQL?

I have 3 tables.
For simplicity I changed them to these sample tables.
table1: CorporateActionSmmary
RATE Quantity ProductID
--------------------------
56 0 1487
30 0 1871
40 0 8750
table2# ProductMaster
RATEGROSS ISIN ProductID
--------------------------
60 JP0001 1487
33 JP0002 1871
45 JP0003 8750
table3# OpenPosition
Quantity ProductID
-------------------
5 1487
1 1487
5 1487
3 1871
2 1871
4 8750
2 8750
7 8750
3 8750
First I need to add ISIN from table2 to table1
table1: CorporateActionSmmary
RATE Quantity ProductID ISIN
-------------------------------------
56 0 1487 JP0001
30 0 1871 JP0002
40 0 8750 JP0003
So, I used this code
SELECT [dbo].[CorporateActionSummary].*, [dbo].[ProductMaster].[ISIN]
FROM [dbo].[CorporateActionSummary] JOIN [dbo].[ProductMaster] ON CorporateActionSummary.ProductID = ProductMaster.ProductID
Now as you can see the Quantity is missing in Table1 so I have to add-up all the quantities in Table3 for each product ID and add to Table1(as a new column or over-write the Quntity column)
I think I can get the sum of each ProductID's Quantity by the following code, But how can I add it to Table1 that already has ISIN column
SELECT SUM(Qantity),ProductID
FROM [dbo].[OpenPositions]
I am super new to SQL, please explain in detail if it is possible, thank you
I am using Microsoft SQL Server Management Studio
you can sum the quantities and then join with your query like so:
SELECT CA.*, PM.[ISIN],CA.Quantity
FROM [dbo].[CorporateActionSummary] CA
JOIN [dbo].[ProductMaster] PM
ON CA.ProductID = PM.ProductID
JOIN (
SELECT ProductID, SUM(Qantity) Quantity
FROM [dbo].[OpenPositions]
GROUP BY ProductID
) OO
on OO.ProductID = CA.ProductID
you are almost there.. you just need to use the same logic to join to the product master table. However, since you need the total of quantity, you need to group by the other columns you select (but not aggregate).
The query will be something like this :
SELECT
[dbo].[CorporateActionSummary].ProductID
, [dbo].[ProductMaster].[ISIN]
,sum([OpenPosition].Quantity) as quantity
FROM [dbo].[CorporateActionSummary]
JOIN [dbo].[ProductMaster]
ON CorporateActionSummary.ProductID = ProductMaster.ProductID
JOIN [dbo].[OpenPosition]
ON CorporateActionSummary.ProductID = OpenPosition.ProductID
group by
[dbo].[CorporateActionSummary].ProductID
, [dbo].[ProductMaster].[ISIN]
if you want to add more columns to your select, then you need to group by those colums as well

Getting latest price of different products from control table

I have a control table, where Prices with Item number are tracked date wise.
id ItemNo Price Date
---------------------------
1 a001 100 1/1/2003
2 a001 105 1/2/2003
3 a001 110 1/3/2003
4 b100 50 1/1/2003
5 b100 55 1/2/2003
6 b100 60 1/3/2003
7 c501 35 1/1/2003
8 c501 38 1/2/2003
9 c501 42 1/3/2003
10 a001 95 1/1/2004
This is the query I am running.
SELECT pr.*
FROM prices pr
INNER JOIN
(
SELECT ItemNo, max(date) max_date
FROM prices
GROUP BY ItemNo
) p ON pr.ItemNo = p.ItemNo AND
pr.date = p.max_date
order by ItemNo ASC
I am getting below values
id ItemNo Price Date
------------------------------
10 a001 95 2004-01-01
6 b100 60 2003-01-03
9 c501 42 2003-01-03
Question is, is my query right or wrong? though I am getting my desired result.
Your query does what you want, and is a valid approach to solve your problem.
An alternative option would be to use a correlated subquery for filtering:
select p.*
from prices p
where p.date = (select max(p1.date) from prices where p1.itemno = p.itemno)
The upside of this query is that it can take advantage of an index on (itemno, date).
You can also use window functions:
select *
from (
select p.*, rank() over(partition by itemno order by date desc) rn
from prices p
) p
where rn = 1
I would recommend benchmarking the three options against your real data to assess which one performs better.

Find Duplicates in a table

My table contains multiple lots (LOT_ID) and each lot contains multiple products(PRODUCT_ID) and there are multiple orders (ORDER_ID) under each Product. I would like to know the order ID’s which are repeated for multiple products for a given LOT
S.NO LOT_ID Product_ID Order_ID
1 101 P108 90001
2 101 P109 90001
3 101 P110 80900
4 102 S189 10098
5 102 S234 10087
6 102 S465 10098
7 102 S342 10050
8 103 L109 20090
9 103 L110 20098
10 103 L111 20020
Desired result
S.NO LOT_ID Product_ID Order_ID
1 101 P108 90001
2 101 P109 90001
3 102 S189 10098
4 102 S465 10098
I think you should apply group by on order_id first and you will get the result set. Please check the answer posted, However I haven't run this.
select LOT_ID, Product_ID, Order_ID
from <tableName>
where Order_ID IN (SELECT Order_ID FROM <tableName> where LOT_ID in (101,102)
GROUP BY Order_ID HAVING COUNT(*) > 1);
count repeats and then select the quantity you need
select t.*, count(*) over (partition by t.LOT_ID, t.Product_ID, t.Order_ID) as c
, count(*) over (partition by t.LOT_ID, t.Order_ID) as c2
from t
When count of unique strings is not equal count of unique Lots and Orders - is your case.

How to Retrieve Maximum Value of Each Group? - SQL

There is a table tbl_products that contains data as shown below:
Id Name
----------
1 P1
2 P2
3 P3
4 P4
5 P5
6 P6
And another table tbl_inputs that contains data as shown below:
Id Product_Id Price Register_Date
----------------------------------------
1 1 10 2010-01-01
2 1 20 2010-10-11
3 1 30 2011-01-01
4 2 100 2010-01-01
5 2 200 2009-01-01
6 3 500 2011-01-01
7 3 270 2010-10-15
8 4 80 2010-01-01
9 4 50 2010-02-02
10 4 92 2011-01-01
I want to select all products(id, name, price, register_date) with maximum date in each group.
For Example:
Id Name Price Register_Date
----------------------------------------
3 P1 30 2011-01-01
4 P2 100 2010-01-01
6 P3 500 2011-01-01
10 P4 92 2011-01-01
select
id
,name
,code
,price
from tbl_products tp
cross apply (
select top 1 price
from tbl_inputs ti
where ti.product_id = tp.id
order by register_date desc
) tii
Although is not the optimum way you can do it like:
;with gb as (
select
distinct
product_id
,max(register_date) As max_register_date
from tbl_inputs
group by product_id
)
select
id
,product_id
,price
,register_date
from tbl_inputs ti
join gb
on ti.product_id=gb.product_id
and ti.register_date = gb.max_register_date
But as I said earlier .. this is not the way to go in this case.
;with cte as
(
select t1.id, t1.name, t1.code, t2.price, t2.register_date,
row_number() over (partition by product_id order by register_date desc) rn
from tbl_products t1
join tbl_inputs t2
on t1.id = t2.product_id
)
select id, name, code, price, register_date
from cte
where rn = 1
Something like this..
select id, product_id, price, max(register_date)
from tbl_inputs
group by id, product_id, price
you can use the max function and the group by clause. if you only need results from the table tbl_inputs you even don't need a join
select product_id, max(register_date), price
from tbl_inputs
group by product_id, price
if you need field from the tbl_prducts you have to use a join.
select p.name, p. code, i.id, i.price, max(i.register_date)
from tbl_products p join tbl_inputs i on p.id=i.product_id
grooup by p.name, p. code, i.id, i.price
Try this:
SELECT id, product_id, price, register_date
FROM tbl_inputs T1 INNER JOIN
(
SELECT product_id, MAX(register_date) As Max_register_date
FROM tbl_inputs
GROUP BY product_id
) T2 ON(T1.product_id= T2.product_id AND T1.register_date= T2.Max_register_date)
This is, of course, assuming your dates are unique. if they are not, you need to add the DISTINCT Keyword to the outer SELECT statement.
edit
Sorry, I didn't explain it very well. Your dates can be duplicated, it's not a problem as long as they are unique per product id. if you can have duplicated dates per product id, then you will have more then one row per product in the outcome of the select statement I suggested, and you will have to find a way to reduce it to one row per product.
i.e:
If you have records like that (when the last date for a product appears more then once in your table with different prices)
id | product_Id | price | register_date
--------------------------------------------
1 | 1 | 10.00 | 01/01/2000
2 | 1 | 20.00 | 01/01/2000
it will result in having both of these records as outcome.
However, if the register_date is unique per product id, then you will get only one result for each product id.

MS Access SQL Query - Showing total number of orders in a certain year

SQL appears to be more complex than I anticipated. My problem: for each customer, I would like to show the Customer ID and the total number of orders placed in 2011.
My table looks like this
Table: Order_t
Order_ID Order_Date Customer_ID
-------- ---------- -----------
1001 10/21/2011 1
1002 10/25/2011 8
1003 10/26/2011 15
1004 10/27/2011 5
1005 11/24/2011 3
1006 11/27/2011 2
1007 11/28/2011 11
1008 12/3/2011 12
1009 12/5/2011 1
1010 1/16/2012 4
I would like my query to display a table like this:
Customer_ID Orders_Placed
----------- -------------
1 2
2 1
3 1
5 1
8 1
11 1
12 1
15 1
My current query is this (I am currently completely neglecting the Date part because I haven't even figured out the grouping yet:
SELECT Customer_ID, SUM(Order_ID) AS Orders_Placed
FROM Order_t
GROUP BY Order_ID, Customer_ID
And this is my obviously wrong query:
Customer_ID Orders_Placed
----------- -------------
1 1001
8 1002
15 1003
5 1004
3 1005
2 1006
11 1007
12 1008
1 1009
4 1010
Thanks for help, but I would also like to understand where the problem is in my logic. What crucial part do I seem to not understand?
The problem with your logic is this
GROUP BY Order_ID, Customer_ID
Which means each combination of (Order_ID, Customer_ID) is put in a different GROUP. Since Order_ID alone is unique, practically no grouping is happening.
To do it correctly, you need to GROUP BY the Customer_ID (it reads like what you need, doesn't it), then COUNT the Orders. Finally, add the date filter as well.
SELECT Customer_ID, COUNT(Order_ID) AS Orders_Placed
FROM Order_t
WHERE Order_Date >= #1/1/2011# and Order_Date < #1/1/2012#
GROUP BY Customer_ID
Use count() instead
SELECT Customer_ID, COUNT(Order_ID) AS Orders_Placed
FROM Order_t
GROUP BY Customer_ID