Query showing exchange rates by date - sql

Apologies if this is silly question...
I have a table that holds rates for multiple currencies at differing dates, as follows:
+-----------------------------+
| FOREKEY FOREDATE FORERATE |
+-----------------------------+
| 1 01/01/16 1.5 |
| 2 01/01/16 1.9 |
| 3 01/01/16 9.2 |
| 4 01/01/16 1.0 |
| 2 01/02/16 1.7 |
| 3 01/03/16 9.0 |
| 4 01/04/16 1.1 |
+-----------------------------+
I would like to create a query that gives the prevailing currency rate at any of the given dates.
I have tried the query below, but this does not show the FOREKEY 1 rate on 01/03/16, for example.
SELECT
F.FOREDATE,
F.FOREKEY,
F.FORERATE
FROM
FORERATE F
INNER JOIN
(SELECT
MAX(FOREDATE) FOREDATE
FROM
FORERATE
GROUP BY
FOREDATE) FSUB
ON (F.FOREDATE = FSUB.FOREDATE) OR (F.FOREDATE > FSUB.FOREDATE)
Any help gratefully received!

You could use a SELECT MAX() in the where clause like below:
SELECT
F.FOREDATE,
F.FOREKEY,
F.FORERATE
FROM FORERATE F
WHERE F.FOREDATE = (SELECT MAX(FOREDATE)
FROM FORERATE FMD
WHERE F.FOREKEY=FMD.FOREKEY)

Related

How to use ID JOIN instead of DATEDIFF()

Write a SQL query to find all dates' id with a higher temperature compared to its previous dates (yesterday).
Try out if you want: https://leetcode.com/problems/rising-temperature/
Input:
Weather table:
+----+------------+-------------+
| id | recordDate | temperature |
+----+------------+-------------+
| 1 | 2015-01-01 | 10 |
| 2 | 2015-01-02 | 25 |
| 3 | 2015-01-03 | 20 |
| 4 | 2015-01-04 | 30 |
+----+------------+-------------+
Output:
+----+
| id |
+----+
| 2 |
| 4 |
+----+
Here's my code:
SELECT w_2.id AS "Id"
FROM Weather w_1
JOIN Weather w_2
ON w_1.id + 1 = w_2.id
WHERE w_1.temperature < w_2.temperature
But my code won't be accepted even if it looks exactly like the expected output.
I know the answer is:
SELECT w2.id
FROM Weather w1, Weather w2
WHERE w2.temperature > w1.temperature
AND DATEDIFF(w2.recordDate, w1.recordDate) = 1
But I tried to not use DATEDIFF because this function is not available in PostgreSQL.
The queries are not compatible. You should join the table on recordDate, not on Id.
SELECT w_2.id AS "Id"
FROM Weather w_1
JOIN Weather w_2
ON w_1.recordDate + 1 = w_2.recordDate
WHERE w_1.temperature < w_2.temperature
Do not assume that Id is sequential and ordered in the same way as recordDate, although the sample data may suggest this.

Joining Two SQL Tables on Different Databases [duplicate]

This question already has answers here:
Can we use join for two different database tables?
(2 answers)
Closed 4 years ago.
I have two tables on two separate databases. We will call them Table1 and Table2.
Table1:
+----------+----------+----------+---------+------+----------+
| UniqueID | Date1 | Date2 | Fruit | Cost | Duration |
+----------+----------+----------+---------+------+----------+
| 1 | 09/10/18 | 10/20/18 | Apples | 1.50 | 7 |
| 2 | 09/18/18 | 10/25/18 | Oranges | 1.75 | 10 |
| 3 | 10/01/18 | 10/30/18 | Bananas | 2.00 | 10 |
+----------+----------+----------+---------+------+----------+
Table2:
+----------+---------+------+----------+-----------+
| Date1 | Fruit | Cost | Duration | New Price |
+----------+---------+------+----------+-----------+
| 09/10/18 | Savory | 1.50 | 7 | 1.90 |
| 09/18/18 | Citrusy | 1.75 | 10 | 2.50 |
| 10/01/18 | Mealy | 2.00 | 10 | 2.99 |
| 10/20/18 | Savory | 1.50 | 7 | 3.90 |
| 10/25/18 | Citrusy | 1.75 | 10 | 4.50 |
| 10/30/18 | Mealy | 2.00 | 10 | 5.99 |
+----------+---------+------+----------+-----------+
What I need the output to look like:
+----------+----------+--------------------+----------+--------------------+
| UniqueID | Date1 | New Price on Date1 | Date2 | New Price on Date2 |
+----------+----------+--------------------+----------+--------------------+
| 1 | 09/10/18 | 1.90 | 10/20/18 | 3.90 |
| 2 | 09/18/18 | 2.50 | 10/25/18 | 4.50 |
| 3 | 10/01/18 | 2.99 | 10/30/18 | 5.99 |
+----------+----------+--------------------+----------+--------------------+
I need to first convert table1.fruit to the representation of table2.fruit (apples-->savory, oranges-->citrusy, bananas-->mealy) then join on table1.fruit = table2.fruit, table1.duration = table2.duration, table1.cost = table2.cost, table1.date1 = table2.date1, and table1.date2 = table2.date1.
I don't know where to start on writing the statement. I looked over some previous questions posted here, but they really just go over the basics of linking two tables from different databases. Do I convert the table1.fruit first in the select statement, then join, or do I convert table1.fruit in the join statement? How do I join table2.date1 on both table1.date1 and table1.date2 to get the price associated with both dates?
If I can provide any more information for you, please let me know.
I am on SQL Server 2017 using Management Studio.
Thanks for any help in advance!
Create a mapping table to bridge between the different codes for fruits.
IF OBJECT_ID('tempdb..#FruitMappings') IS NOT NULL
DROP TABLE #FruitMappings
CREATE TABLE #FruitMappings (
Table1Fruit VARCHAR(100),
Table2Fruit VARCHAR(100))
INSERT INTO #FruitMappings (
Table1Fruit,
Table2Fruit)
VALUES
('Apples', 'Savory'),
('Oranges', 'Citrusy'),
('Bananas', 'Mealy')
SELECT
T1.*
--, whichever columns you need
FROM
Database1.Schema1.Table1 AS T1
INNER JOIN #FruitMappings AS F ON T1.Fruit = F.Table1Fruit
INNER JOIN Database2.Schema2.Table2 AS T2 ON
F.Table2Fruit = T2.Fruit AND
T1.Cost = T2.Cost AND
T1.Duration = T2.Duration
-- AND any other matches you need
You can use LEFT JOIN or even FULL JOIN, depending if you might have some fruits on a table that aren't available on the other (careful with NULL values if FULL JOIN).
If both databases are on the same SQL Server instance and your SQL Server login has access to both databases you can just use the full form of the object names:
select * -- Whatever...
from Database1.dbo.Table1 t1
inner join Database2.dbo.Table2 t2
on t1,UniqueId = t2.UniqueId -- Or whatever your join condition is
(adding where etc. clauses as required.)
This assumes both databases are using the default schema, otherwise replace dbo as necessary.
If the databases are on different servers you can use linked servers, but there are performance implications (the whole remote table may be read because the optimiser can't do much to filter it).

Convert rows to columns for a Report

Using instructions found here I've tried to create a crosstab query to show historical data from three previous years and I would like to output it in a report.
I've got a few complications that are making this difficult and I'm having trouble getting the data to show correctly.
The query it is based on is structured like this:
EmpID | ReviewYearID | YearName | ReviewDate | SelfRating | ManagerRating | NotSelfRating |
1 | 5 | 2013 | 01/09/2013 | 3.5 | 3.5 | 3.5 |
1 | 6 | 2014 | 01/09/2014 | 2.5 | 2.5 | 2.5 |
1 | 7 | 2015 | 01/09/2015 | 4.5 | 4.5 | 4.5 |
2 | 6 | 2014 | 01/09/2014 | 2.0 | 2.0 | 2.0 |
2 | 7 | 2015 | 01/09/2015 | 2.0 | 2.0 | 2.0 |
3 | 7 | 2015 | 01/09/2015 | 5.0 | 5.0 | 5.0 |
[Edit]: Here is the SQL for the base query. It is combining data from two tables:
SELECT tblEmployeeYear.EmployeeID AS EmpID, tblReviewYear.ID AS ReviewYearID, tblReviewYear.YearName, tblReviewYear.ReviewDate, tblEmployeeYear.SelfRating, tblEmployeeYear.ManagerRating, tblEmployeeYear.NotSelfRating
FROM tblReviewYear INNER JOIN tblEmployeeYear ON tblReviewYear.ID = tblEmployeeYear.ReviewYearID;
[/Edit]
I would like a crosstab query that transposes the columns/rows to show historical data for up to 3 previous years (based on review date) for a specific employee. The end result would look something like this for Employee ID 1:
Year | 2015 | 2014 | 2013 |
SelfRating | 4.5 | 2.5 | 3.5 |
ManagerRating | 4.5 | 2.5 | 3.5 |
NotSelfRating | 4.5 | 2.5 | 3.5 |
Other employees would have less columns since they don't have data for previous years.
I'm having issues with filtering it down to a specific employee and sorting the years by their review date (the name isn't always a reliable way to sort them).
In the end I'm looking to use this as the data for a report.
If there is a different way than a crosstab query to accomplish this I would be okay with that as well.
Thanks!
You need a column for all the rating types, not an individual column for each type. If you can't redesign the table, I would suggest creating a new one for your purposes. The below uses a union to add in that type column referred to above. You create a column and hardcode the value (SelfRating, ManagerRating, etc):
SELECT * INTO EmployeeRatings
FROM (SELECT tblEmployeeYear.EmployeeId AS EmpId, ReviewYearId, "SelfRating" AS Category, SelfRating AS Score
FROM tblEmployeeYear
WHERE SelfRating Is Not Null
UNION ALL
SELECT tblEmployeeYear.EmployeeId, ReviewYearId, "ManagerRating", ManagerRating
FROM tblEmployeeYear
WHERE ManagerRating Is Not Null
UNION ALL
SELECT tblEmployeeYear.EmployeeId, ReviewYearId, "NotSelfRating", NotSelfRating
FROM tblEmployeeYear
WHERE NotSelfRating Is Not Null)
Then use the newly created table in place of tblEmployeeYear. Note that I use Year([ReviewDate]) which will return only the year. Also, since it looks like it may be possible to have more than one of each review type per year, I averaged the Score for the year.
TRANSFORM Avg(Score)
SELECT EmpId, Category
FROM (SELECT EmpId, Category, ReviewDate, Score
FROM tblReviewYear
INNER JOIN EmployeeRatings
ON tblReviewYear.ID = EmployeeRatings.ReviewYearID) AS Reviews
GROUP BY EmpId, Category
PIVOT Year([ReviewDate]);

SQL Query - Mathematical Query across 2 tables

I think the Title is a bit off what I need, so if someone thinks of a better title please don't hesitate to change it.
My issue is this: I have a TIMESHEET table, and a RATES table.
The TIMESHEET table looks like this:
|RATE-ID|OT |DAY1|DAY2|DAY3|DAY4|DAY5|DAY6|DAY7|DAY8|DAY9|DAY10|DAY11|DAY12|DAY13|DAY14|
----------------------------------------------------------------------------------------
| 1 |1 | 2 | 3 | 4 | 5 | 6 | 0 | 0 | 7 | 8 | 1 | 2 | 0 | 5 | 6 |
| 5 |1.5| 6 | 5 | 4 | 3 | 2 | 0 | 0 | 1 | 0 | 7 | 6 | 4 | 3 | 2 |
The RATES table looks like this:
|ID| RATE |
|1 | 50.00 |
|2 | 30.00 |
....
|5 | 100.00|
So then what I do in terms of a query (once off, so no worries about SQL injections) is this:
SELECT sum(DAY1)+sum(DAY2)+sum(DAY3)+sum(DAY4)+sum(DAY5)+sum(DAY6)+sum(DAY7)+sum(DAY8)+sum(DAY9)+sum(DAY10)+sum(DAY11)+sum(DAY12)+sum(DAY13)+sum(DAY14) as TOTALHOURS, OT, RATES.RATE from TIMESHEET INNER JOIN RATES on TIMESHEETS.RATE-ID = RATES.ID
Works fantastic - 3 seperate columns that tell me the total hours, the OT multiplier, and the rate. Now comes the part I'm struggling with. I can't seem to multiply the TOTALHOURS column against anything. I can do the simple OT * RATE as NEWRATE and get it down to 2 columns: TOTALHOURS and NEWRATE.
My question is, how do I multiply these two dynamically named columns to get the result?
i.e the first one would be 49 (sum of line 1) * 1 (OT for line 1) * 50 (Rate for line 1) = 2450
Any help is greatly appreciated.
Cheers,
Dee.
If you want a single line query without the hassles of running subqueries, temp tables, CTE's, group by clauses, or what have you, just try cleaning up the query a bit like this:
SELECT sum((DAY1+DAY2+DAY3+DAY4+DAY5+DAY6+DAY7+DAY8+DAY9+DAY10+DAY11+DAY12+DAY13+DAY14) * RATE * OT) as TOTALL FROM from TIMESHEET INNER JOIN RATES on TIMESHEETS.RATE-ID = RATES.ID
SQL has a wide variety of ways to accomplish the same result. Try the different ones and find the type that suits you and the application well.

SQL query to get dif between dates in select statment

I have a two tables call RFS and RFS_History.
RFS_id | name
--------+--------
12 | xx
14 | yy
15 | zz
figure 1 :RFS table
RFS_id | gate | End | start
--------+-------+--------+-------
12 | aa | 19/02 | 20/03
12 | bb | 30/01 | 12/08
12 | cc | 30/01 | 12/08
13 | aa | 30/01 | 12/08
12 | dd | 30/01 | 12/08
figure 2 :RFS history
My initial query is a select * query to get information where FRSname ='xx'
SELECT * FROM RFS, RFSHistory
WHERE RFSname="xx" And RFShistory.RFS_ID=RFS.RFS_ID
result is:
RFS_id | gate | End | start
--------+-------+--------+-------
12 | aa | 19/02 | 19/01
12 | bb | 12/04 | 12/02
12 | cc | 20/03 | 12/03
12 | dd | 30/09 | 12/08
figure 3
however I want to get a result like bellow format :
RFS_id | gate_aa | gate_bb | gate_cc | gate_dd
----------------------------------------------
12 | 30 days | 60dyas | 8days | 18days
gate_aa is duraion and it gets from start - end date. Please help me to write single query to get this result.
Use datediff() to get date difference and Pivot() to convert row into cloumn
like here in your case gate wise column
Sample Syntax
SELECT DATEDIFF(day,'2008-06-05','2008-08-05') AS DiffDate
You can use the below query for get the difference b/w dates
SELECT RFS.ID,(RFS_HISTORY.end_t-RFS_HISTORY.start_t) AS DiffDate,gate FROM RFS, RFS_HISTORY
WHERE name='aa' And RFS_HISTORY.ID=RFS.ID group by RFS.ID,gate,RFS_HISTORY.end_t,RFS_HISTORY.start_t
I think you want to convert rows into columns on the values. This can be done with the help of pivoting.
SELECT * FROM RFS, RFSHistory
pivot for columname on [values]
I actually forgot the syntax but you can google it