How to add a query to a table in SQL? - 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

Related

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.

Access sql Moving Average of Top N With 2 criterias

I have been searching the forum and found a single post that is a little smilair to my problem here: Calculate average for Top n combined with SQL Group By.
My situation is:
I have a table tblWEIGHT that contains: ID, Date, idPONR, Weight
I have a second table tblSALES that contains: ID, Date, Sales, idPONR
I have a third table tblPONR that contains: ID, PONR, idProduct
And a fouth table tblPRODUCT that contais: ID, Product
The linking:
tblWEIGHT.idPONR = tblPONR.ID
tblSALES.idPONR = tblPONR.ID
tblPONR.idProduct = tblPRODUCT.ID
The maintable of my query is tblSALES. I want to all my sales listed, with the moving average of the top5
weights of the PRODUCT where the date of the weight is less than the sales date, and the product is the same as the sold product. Its IMPORTANT that the result isn't grouped by the date. I need all the records of tblSALES.
i have gotten as far as to get the top 1 weight, but im not able to get the moving average instread.
The query that gest the top 1 is the following, and i am guessing that the query i need is going to look a lot like it.
SELECT tblSALES.ID, tblSALES.Dato, tblPONR.idPRODUCT,
(
SELECT top 1 Weight FROM tblWEIGHT INNER JOIN tblPONR ON tblWeight.idPONR = tblPONR.ID
WHERE tblPONR.idPRODUCT = idPRODUCT AND
SALES.Date > tblWEIGHT.Date
ORDER BY tblWEIGHT.Date desc
) AS LatestWeight
FROM tblSALES INNER JOIN VtblPONR ON tblSALES.idPONR = tblPONR.ID
this is not my exact query since im danish and i wouldnt make sense. I know im not supposed to use Date as a fieldname.
i imagine the filan query would be something like:
SELECT tblSALES.ID..... avg(SELECT TOP 5 weight .........)
but doing this i keep getting error at max 1 record can be returned by this subquery
Final Question.
How do i make a query that creates a moving average of the top 5 weights of my sold product, where the date of the weight is earlier than the date i sold the product?
EDIT Sampledata:
DATEFORMAT: dd/mm/yyyy
tblWEIGHT
ID Date idPONR Weight
1 01-01-2020 1 100
2 02-01-2020 2 200
3 03-01-2020 3 200
4 04-01-2020 3 400
5 05-01-2020 2 250
6 06-01-2020 1 150
7 07-01-2020 2 200
tblSALES
ID Date Sales(amt) idPONR
1 05-01-2020 30 1
2 06-01-2020 15 2
3 10-01-2020 20 3
tblPONR
ID PONR(production Number) idProduct
1 2521 1
2 1548 1
3 5484 2
tblPRODUCT
ID Product
1 Bricks
2 Tiles
Desired outcome read comments for AvgWeight
tblSALES.ID tblSALES.Date tblSales.Sales(amt) AvgWeigt
1 05-01-2020 30 123 -->avg(top 5 newest weight of both idPONR 1 And 2 because they are the same product, and where tblWeight.Date<05-01-2020)
2 06-01-2020 15 123 -->avg(top 5 newest weight of both idPONR 1 And 2 because they are the same product, and where tblWeight.Date<06-01-2020)
3 10-01-2020 20 123 -->avg(top 5 newest weight of idPONR 3 since thats the only idPONR with that product, and where tblWeight.Date<10-01-2020)
Consider:
Query1
SELECT tblWeight.ID AS WeightID, tblWeight.Date AS WtDate,
tblWeight.idPONR, tblPONR.PONR, tblPONR.idProduct, tblWeight.Weight, tblSales.SalesAmt,
tblSales.ID AS SalesID, tblSales.Date AS SalesDate
FROM (tblPONR INNER JOIN tblWeight ON tblPONR.ID = tblWeight.idPONR)
INNER JOIN tblSales ON tblPONR.ID = tblSales.idPONR;
Query2
SELECT * FROM Query1 WHERE WeightID IN (
SELECT TOP 5 WeightID FROM Query1 AS Dupe WHERE Dupe.idProduct = Query1.idProduct
AND Dupe.WtDate<Query1.SalesDate ORDER BY Dupe.WtDate);
Query3
SELECT Query2.SalesID, Query2.SalesDate, Query2.SalesAmt,
First(DAvg("Weight","Query2","idProduct=" & [idProduct] & " AND WtDate<#" & [SalesDate] & "#")) AS AvgWt
FROM Query2
GROUP BY Query2.SalesID, Query2.SalesDate, Query2.SalesAmt;

SQL Inner Join - getting max value

2 tables related with recordKey:
Transaction Table
TransId recordKey
44 111
56 234
History Table
HistoryId recordKey ProcessTime
1 111 0
2 111 200
3 111 4000
4 234 10
How to join this table so that when group by, will get the max process time only (4000)?
Update: The result will look like this:
TransId ProcessTime
44 4000
55 10
SELECT transId, MAX(processTime)
FROM transaction
JOIN history ON history.recordKey = transaction.recordKey
GROUP BY transId
maybe something like this?
select transid,transaction.recordkey,max(history.processtime)
from transaction, history
where transaction.recordkey=history.recordkey
group by transid,transaction.recordkey

SQL multiple 1-to-many joins

I'm almost certain I've run into this before and am just having an extended senior moment, but I am trying to pull work order data from three different tables across 2 db's on a SQL instance and combine it all into a report, I'm looking for the end result to contain the following columns:
WO | Production Recorded Qty | Inventory Qty | Variance
The Variance part is easy I can just nest the select statement, and subtract the two quantities in the outer statement, but the problem I'm running in to is when I join the production and Inventory tables in their corresponding databases I end up getting sums of the columns that I'm targeting that are way larger than what they should be
Sample Data:
Work Order, Short P/N, and Long P/N in Work Order Table:
dba.1
WO ShortPN LongPN
152 1234 Part1
Short P/N, Quantity on hand, location, and lot # in inventory table:
dba.2
ShortPN Qty Loc Lot
1234 31 Loc1 456
1234 0 Loc2 456
1234 0 Loc4 456
1234 19 Loc1 789
1234 25 Loc4 789
Work Order, Long P/N, and production count of the last 5min in Production table:
dbb.3
WO LongPN Count
152 Part3 6
152 Part3 8
152 Part3 9
152 Part3 4
152 Part3 6
152 Part3 7
With this example I've tried:
SELECT 1.WO AS WO
,SUM(2.Qty) AS "Qty On Hand"
,SUM(3.Count) AS "Produced Qty"
FROM dba.1
INNER JOIN dbb.2 ON 1.ShortPN=2.ShortPN
INNER JOIN dbb.3 ON 1.WO = 3.WO
GROUP BY 1.WO
I've also tried selecting from 3, joining 1 to 3 on the WO, then 2 to 1 on shortPN, and both yield SUM() numbers that are exponentially higher than they should be(ie what should be 15,xxx turns into over 2,000,000), however if I remove one of the data points from the report and select just the inventory or production qty I get the correct end results. I swear that I've run into this before but for the life of me can't remember how it was solved, sorry if it's a duplicate question as well, couldn't find anything by searching.
Thanks in advance for the help, it's greatly appreciated.
You can do something like this
select
WO.WO, isnull(i.Qty, 0) as Qty, isnull(p.[Count], 0) as [Count]
from WorkOrder as WO
left outer join (select t.ShortPN, sum(t.Qty) as Qty from inventory as t group by t.ShortPN) as i on
i.ShortPN = WO.ShortPN
left outer join (select t.WO, sum(t.[Count]) as [Count] from Production as t group by t.WO) as p on
p.WO = WO.WO
SQL FIDDLE example
if you have SQL Server 2005 or higher, you can write it like this
select
WO.WO, isnull(i.Qty, 0) as Qty, isnull(p.[Count], 0) as [Count]
from WorkOrder as WO
outer apply (select sum(t.Qty) as Qty from inventory as t where t.ShortPN = WO.ShortPN) as i
outer apply (select sum(t.[Count]) as [Count] from Production as t where t.WO = WO.WO) as p
SQL FIDDLE example
this happens because when you make a join of WO and inventory tables you got
WO SHORTPN QTY
-------------------
152 1234 31
152 1234 0
152 1234 0
152 1234 19
152 1234 25
and you see that now you have 5 rows with WO = 152. When you add join with Production table, for each row with WO = 152 from this join there will be 6 rows with WO = 152 from Production table, so you will have 30 rows total and QTY from inventory will be listed 6 times each. When you sum this up, instead of 75 you will have 75 * 6 = 450. And for Count you'll have each Count * 5, so instead of 40 you'll have 200.

How to get Result from database by order the condition put in "IN" clause?

Sorry for bad english.
bfproduct is a table and productid is primary key in this table and productname is another field defined in this table.
When i execute this query, select * from bfproduct where productid in (23,5,54,3132,32). The result is as follows:
productid | productname
5 15 Park Avenue
23 Good Boy Bad Boy
32 dsf sf gfdsf dsf d
54 dsdsfsa ffs ff sfsf
3132 Just Books - On The Failure of Legal System
Is there any way i will get the resultset in the order by the productid provided in "IN" Clause e.g.
productid | productname
23 Good Boy Bad Boy
5 15 Park Avenue
54 dsdsfsa ffs ff sfsf
3132 Just Books - On The Failure of Legal System
32 dsf sf gfdsf dsf d
Please help...
Here's one way to do it:
SELECT *
FROM bfproduct
WHERE productid
IN (23,5,54,3132,32)
ORDER BY
CASE productid
WHEN 23 THEN 0
WHEN 5 THEN 1
WHEN 54 THEN 2
WHEN 3132 THEN 3
WHEN 32 THEN 4
END
First thing I can think of, try something like...
select bfproduct.*
from bfproduct INNER JOIN
(
select 1 as sequence, 23 as productid
union
select 2,5
union
select 3,54
union
select 4,3132
union
select 5,32
) as lookup on bfproduct.productid=lookup.productid
order by lookup.sequence
(I haven't tested this so there maybe some minor syntax errors!)
You have to add a ORDER BY clause that puts the rows to correct order.