Imagine we have 2 Tables, A and B, having the same structure, as follows:
Currency, Spot, Exposure, Fixing.
We want to join these two tables in order to have a query on, for example, Fixing = '2013-01-03' and having the major list of currencies (there is not always correspondence between currencies in A and currencies in B).
1 condition: A.Fixing = B.Fixing
2 condition: A.Currency = B.Currency (returning also Currency values not matched)
This is an example: We have the USD currency in table A for that day requested but we don't have it on table B. What we want for that day is a join table having one row with USD followed by the Exposure value in Table A and followed by zero (because ARS was not in table B and therefore it has no Exposure on USD)
How can we write a query?
Below Tables and results:
Table A:
Currency Spot Exposure Fixing
-------- ------- ------------ ----------
AUD 1.3023 -504,561.00 30/01/2013
CHF 1.2378 268,243.00 30/01/2013
GBP 0.8597 2,204.00 30/01/2013
JPY 123.635 -552.00 30/01/2013
USD 1.3572 5,242.00 30/01/2013
AUD 1.300 -574,561.00 29/01/2013
CHF 1.235 545,152.00 29/01/2013
GBP 0.858 1,155,212.00 29/01/2013
JPY 123.388 -45,115.00 29/01/2013
USD 1.354 22,468.00 29/01/2013
Table B:
Currency Spot Exposure Fixing
-------- ------- ------------- ----------
AUD 1.3023 256,442.00 30/01/2013
CHF 1.2378 -4,456,421.00 30/01/2013
GBP 0.8597 15,246.00 30/01/2013
JPY 123.635 1,243,146.00 30/01/2013
AUD 1.300 41,246.00 29/01/2013
CHF 1.235 243.00 29/01/2013
GBP 0.858 54,564.00 29/01/2013
JPY 123.388 140.00 29/01/2013
Results:
Currency A.Exposure B.Exposure Fixing
-------- ----------- ------------- ----------
AUD -504,561.00 256,442.00 30/01/2013
CHF 268,243.00 -4,456,421.00 30/01/2013
GBP 2,204.00 15,246.00 30/01/2013
JPY -552.00 1,243,146.00 30/01/2013
USD 5,242.00 - 30/01/2013
EDITED: The left outer join allows you to grab everything in table a and matching values in table b and having NULLs where there isn't data in table b. Use the ISNULL() function to give you cleaner results by checking for NULL values and if it finds one, replacing it with a different value of your choosing.
select
a.Currency
, a.Spot
, a.Exposure as a_Exposure
, ISNULL(b.Exposure, 0) as b_Exposure
, a.Fixing
from a
left outer join b
on b.Currency = a.Currency
and b.Fixing = a.Fixing
where a.Fixing = '2013-01-30';
I have changed the query to reflect the suggestion from Clockwork-Muse. You will need to add any columns you want data returned for.
Related
I have a table in Presto that looks like
Date
Rates
1/1/2022
{"USD":"725.275","GBP":"29.275000000000002","CAD":"0.713352"}
1/2/2022
{"USD":"745.275","GBP":"40.275000000000002","CAD":"0.813352"}
What I'd like it to resemble as output of the query is:
Date Currency Rate
1/1/2022 USD 725.275
1/2/2022 USD 745.275
1/1/2022 GBP 29.275
1/2/2022 GBP 40.275
1/1/2022 CAD 0.713352
1/2/2022 CAD 0.813352
But can't seem to figure it out using the their documentation.
Assuming Rates is column of JSON type (otherwise use json_parse) and you don't want to handle every currency "manually" with json_extract_scalar (json_extract_scalar(Rates, '$.USD'), json_extract_scalar(Rates, '$.GBP'), ...) - common way to handle such "dynamic" json is to cast it to map (for example map(varchar, double) in this case) and use unnest:
WITH dataset ( Date,Rates) AS (
VALUES ('1/1/2022', json '{"USD":"725.275","GBP":"29.275000000000002","CAD":"0.713352"}'),
('1/2/2022', json '{"USD":"745.275","GBP":"40.275000000000002","CAD":"0.813352"}')
)
--query
select date, currence, rate
from dataset
cross join unnest(cast(rates as map(varchar, double))) t(currence, rate)
Output:
date
currence
rate
1/1/2022
CAD
0.713352
1/1/2022
GBP
29.275000000000002
1/1/2022
USD
725.275
1/2/2022
CAD
0.813352
1/2/2022
GBP
40.275
1/2/2022
USD
745.275
I have table Price:
WhseKey ItemKey CurrID Sheet1Price Sheet2Price Sheet3Price Sheet4Price
24 452 USD 14.90000 14.90000 13.70000 12.50000 11.03000
24 453 USD 1.15000 1.15000 1.05000 0.95000 0.85000
24 454 USD 12.95000 12.95000 11.90000 10.88000 9.70000
24 459 USD 3.95000 3.95000 3.65000 3.30000 2.92000
I want the result to be like:
CurrID Name ID
USD Sheet1Price Sheet1Price
USD Sheet2Price Sheet2Price
USD Sheet3Price Sheet3Price
USD Sheet4Price Sheet4Price
Current query:
select UPV.CurrID , UPV.Name
from Price
unpivot
(
Name
for Price in (Sheet1Price, Sheet2Price, Sheet3Price, Sheet4Price)
) UPV;
But the result is not correct, it comes as:
CurrID Name
USD 14.90000
USD 13.70000
USD 12.50000
USD 11.03000
USD 1.15000
USD 1.05000
USD 0.95000
USD 0.85000
USD 12.95000
USD 11.90000
What i am missing?
To output filed names you should use UPV.Price, Try this:
select WhseKey, ItemKey, UPV.CurrID , UPV.Name, UPV.Price
from Price
unpivot
(
Price
for Name in (Sheet1Price, Sheet2Price, Sheet3Price, Sheet4Price)
) UPV;
I have two tables which contain orders. I need to check that the tables match up. The table look something like below,
tblOrders_Sent
Side Tag FxBuy BuyAmount FxCost CostAmount
B CHFEUR CHF 50 EUR 0
B EURSEK SEK 75 EUR 0
B EURNOK NOK 35 EUR 0
B DKKEUR DKK 20 EUR 0
S CHFEUR EUR 0 CHF 10
S EURSEK EUR 0 SEK 20
S EURNOK EUR 0 NOK 40
tblOrders_Recieved
Tag FxBuy MktBuy FxCost MktCost
EURNOK NOK 35 EUR 0
DKKEUR DKK 20 EUR 0
CHFEUR CHF 50 EUR 0
EURSEK SEK 75 EUR 0
EURNOK EUR 0 NOK 40
EURSEK EUR 0 SEK 20
CHFEUR EUR 0 CHF 10
When the Side is "B" in the Orders_Sent table I need to check the BuyAmount against the MktBuy amount in the Orders_Recieved table. If the Side is "S" though I need to check the CostAmount vs the MktCost in the Orders_Recieved table. Is this possible or do I need to split the query into two seperate queries?
I'm using SQL Server 2012
Desired Output
FxBuy FxCost SentAmt RecievedAmt Diff
CHF EUR 50 50 0
SEK EUR 75 75 0
NOK EUR 35 35 0
DKK EUR 20 20 0
EUR CHF 10 10 0
EUR SEK 20 20 0
EUR NOK 40 40 0
The CASE keyword helps there. In your case as far as I understood the example it could look like this:
select
tblOrders_sent.fxBuy As FxBuy,
tblorders_sent.fxCost As FxCost,
tblorders_sent.buyamount as SentAmt,
tblorders_received.mktbuy as ReceivedAmt,
CASE Side WHEN 'B' THEN tblorders_sent.buyamount - tblorders_received.mktbuy END
tblorders_sent.costamount - tblorders_received.mktcost END AS diff
from tblOrders_sent
inner join tblOrders_received on
tblorders_sent.tag = tblorders_received.tag
I need to query an SQL database to find all distinct values of one column and I need an arbitrary value from another two columns. For example, consider the following table with three columns: CurrencyCode, BuyRate and SellRate:
CurrencyCode BuyRate SellRate
AUD 1.037 1.97
AUD 1.079 1.99
EUR 0.7288 0.8763
EUR 0.731 0.88
GBP 0.59 0.72
I wish to retrieve one row with distinct CurrencyCode, perhaps getting these three rows:
CurrencyCode BuyRate SellRate
AUD 1.037 1.97
EUR 0.7288 0.8763
GBP 0.59 0.72
I tried my SQL query like:
SELECT distinct CurrencyCode, BuyRate, SellRate FROM Currencies
But I am not getting the desired result as it districts all the columns.
Try with GROUP BY clause and MIN function as below
SELECT CurrencyCode, MIN(BuyRate), MIN(SellRate)
FROM Currencies
GROUP BY CurrencyCode
Till now I found this is the best answer to get Min(SellRate) on the basis of Min(BuyRate)
eg.
CurrencyCode BuyRate SellRate
AUD 1.037 1.97
AUD 1.079 1.89 //Changed from 1.99 to 1.89
AUD 1.038 1.77 //New row added
EUR 0.7288 0.8763
EUR 0.731 0.88
GBP 0.59 0.72
Here I am expecting AUDrows for BuyRate and SaleRate will be 1.037 and 1.97
select CurrencyCode, Min(BuyRate) as BuyRate,
(select top 1 SellRate from Currencies as C
where C.CurrencyCode=Currencies.CurrencyCode
and
C.BuyRate= Min(Currencies.BuyRate) order by SellRate) as SellRate
from Currencies
group
by CurrencyCode
I hv two tables:-
First Table:-
EFF_DATE RATE CURRENCY TYPE
20110101 1.286 USD 1
20110101 1.300 USD 2
20110201 1.275 USD 1
20110201 1.290 USD 2
20110301 1.275 USD 1
20110301 1.285 USD 2
20110401 1.260 USD 1
20110401 1.270 USD 2
20110501 1.225 USD 1
20110501 1.230 USD 2
2nd Table:-
PO_NO TRANS_DATE ACCT_DATE SUPP_NO CURRENCY LOCAL_AMT
1000068 20110114 20110115 S016 USD 16,500.00
1000070 20110214 20110215 S016 USD 7,660.00
1000072 20110317 20110322 S025 USD 1,080.00
1000132 20110314 20110315 S037 USD 3,500.00
1000133 20110414 20110415 S038 USD 14,500.00
Based on ACCT_DATE & TYPE = 1, I wish to add a RATE column & the result should look like this:-
PO_NO TRANS_DATE ACCT_DATE SUPP_NO CURRENCY LOCAL_AMT RATE
1000068 20110114 20110115 S016 USD 16,500.00 1.286
1000070 20110214 20110215 S016 USD 7,660.00 1.275
1000072 20110317 20110322 S025 USD 1,080.00 1.275
1000132 20110314 20110315 S037 USD 3,500.00 1.275
1000133 20110414 20110415 S038 USD 14,500.00 1.26
1000170 20110531 20110531 S016 USD 15,400.00 1.225
I used the below SQL to run but for some reasons, it just keep looping without any output:-
SELECT st.*, ft.rate
FROM second_table st
LEFT JOIN first_table ft
ON (MONTH(acct_date) = MONTH(eff_date) AND YEAR(acct_date) = YEAR(eff_date) )
where ft.TYPE=1
Pls help.
Thanks.
Not very large. If I remove ft.TYPE=1,
it will generate the result almost
immediately.
Based on your comment above you need to put an index on ft.TYPE
You could also set up the query like this which might improve how the optimizer runs the query
SELECT st.*, ft.rate
FROM second_table st
LEFT JOIN first_table ft
ON ft.TYPE=1 AND MONTH(acct_date) = MONTH(eff_date) AND YEAR(acct_date) = YEAR(eff_date)
Also, are the dates stored as strings or as datetime values. If they are stored as strings you should do a string compare instead of coverting to datetimes and then extracting the month and year.
How large are your tables? Your joining on an agrigate function so it will be very slow if the tables are large