SQL join against date ranges?
You could first do a self-join on the exchange rates which are ordered by date so that you have the start and the end date of each exchange rate, without any overlap or gap in the dates (maybe add that as view to your database - in my case I'm just using a common table expression).
Now joining those "prepared" rates with the transactions is simple and efficient.
Something like:
WITH IndexedExchangeRates AS (
SELECT Row_Number() OVER (ORDER BY Date) ix,
Date,
Rate
FROM ExchangeRates
),
RangedExchangeRates AS (
SELECT CASE WHEN IER.ix=1 THEN CAST('1753-01-01' AS datetime)
ELSE IER.Date
END DateFrom,
COALESCE(IER2.Date, GETDATE()) DateTo,
IER.Rate
FROM IndexedExchangeRates IER
LEFT JOIN IndexedExchangeRates IER2
ON IER.ix = IER2.ix-1
)
SELECT T.Date,
T.Amount,
RER.Rate,
T.Amount/RER.Rate ConvertedAmount
FROM Transactions T
LEFT JOIN RangedExchangeRates RER
ON (T.Date > RER.DateFrom) AND (T.Date <= RER.DateTo)
Notes:
You could replace
GETDATE()
with a date in the far future, I'm assuming here that no rates for the future are known.Rule (B) is implemented by setting the date of the first known exchange rate to the minimal date supported by the SQL Server
datetime
, which should (by definition if it is the type you're using for theDate
column) be the smallest value possible.
Joining two tables by date ranges
If you have access to window functions and CTEs you can simply use LEAD
:
WITH cte AS (
SELECT id, date, LEAD(date, 1) OVER (ORDER BY date) AS end_date
FROM events
)
SELECT cte.id, reference.date AS reference_date, cte.date AS event_date
FROM cte
INNER JOIN reference ON reference.date >= cte.date
AND (reference.date < cte.end_date OR cte.end_date IS NULL)
SQl join on date range
SELECT
name,
date(start_date),
date(end_date),
d.id as Day_Date
FROM f_table1 a
Left Join d_table2 d
on a.id = d.id
and d.`Day Date` between date(a.start_date) and date(a.end_date)
Joining two dataset based on date range
Use BETWEEN
operator.
proc sql;
create table want as
select *
from have1 t1 inner join have2 t2
on t1.id = t2.id
and t2.date BETWEEN t1.date-5 AND t1.date+5
;
quit;
With example data:
data have1;
infile datalines4 delimiter="|";
input id date :date9.;
format date date9.;
datalines4;
1|15DEC2021
2|12NOV2020
3|10JAN2019
;;;;
data have2;
infile datalines4 delimiter="|";
input id date :date9.;
format date date9.;
datalines4;
1|20DEC2021
2|16NOV2020
3|19JAN2019
;;;;
proc sql;
create table want as
select t1.id
from have1 t1 inner join have2 t2
on t1.id = t2.id
and t2.date BETWEEN t1.date-5 AND t1.date+5
;
quit;
Result:
id
1
2
Join Tables on Date Range in Hive
RTFM - quoting LanguageManual Joins
Hive does not support join conditions that are not equality conditions
as it is very difficult to express such conditions as a map/reduce
job.
You may try to move the BETWEEN filter to a WHERE clause, resulting in a lousy partially-cartesian-join followed by a post-processing cleanup. Yuck. Depending on the actual cardinality of your "skill group" table, it may work fast - or take whole days.
Join 2 tables with filter on date range and number
To find rows that aren't matched in another table, you can use the LEFT JOIN/NULL
pattern. When you use a LEFT JOIN
, the conditions on the child table are put into the ON
clause. Conditions on the parent table are put into the WHERE
clause.
SELECT p.*
FROM property_tbl AS p
LEFT JOIN booking_tbl AS b
ON p.id = b.propertyID AND booking_tbl.endDate > '17-10-24' AND booking_tbl.startDate < '17-10-31'
WHERE b.propertyID IS NULL
AND p.max_guest > @num_guest
SQL: How to join two tables by their date ranges
Actually, my variant still does not work correctly. The @MinDate1 and @MinDate2 should be compared by each EmployeeTypeID one by one. There it was compared independently.
Here is correct variant of solving this problem:
SELECT MIN(CASE WHEN t1.ValidFrom > t2.ValidFrom THEN t1.ValidFrom ELSE t2.ValidFrom END) AS MinOverlapDate
FROM Table1 t1
JOIN Table2 t2 ON t1.EmployeeTypeID = t2.EmployeeTypeID
WHERE t1.WorkItemID = 1 AND t2.EmployeeID = 1
AND (t1.ValidFrom <= t2.ValidTo OR t2.ValidTo IS NULL)
AND (t1.ValidTo >= t2.ValidFrom OR t1.ValidTo IS NULL)
Joining tables based on expanded date range
How to implement this range query?
The key is to filter the data twice in each LEFT JOIN
.
- Filter the part whose ask time precede rate time.
- Filter the nearest wanted time by
max
.
- Filter the nearest wanted time by
SELECT * FROM orders o LEFT JOIN currency_rates c
ON c.currency_id = o.currency_id AND c.valid_from = (
SELECT max(valid_from) FROM currency_rates
WHERE valid_from <= o.received_at
);
/* My result:
id | received_at | shipping_cost | currency_id | invoice_address_id | delivery_address_id | currency_id | rate | valid_from
--------+-------------+---------------+-------------+--------------------+---------------------+-------------+--------+------------
385902 | 2020-01-01 | 0 | CZK | 1 | 11 | | |
386284 | 2020-01-08 | 44.03 | EUR | 8 | | EUR | 25.2 | 2020-01-03
386282 | 2020-01-06 | 11.43 | GBP | 6 | | GBP | 28.4 | 2020-01-03
386278 | 2020-01-02 | 12.83 | USD | 2 | | USD | 19.359 | 2019-12-01
386281 | 2020-01-05 | 12.83 | USD | 5 | 14 | USD | 20.34 | 2020-01-03
386279 | 2020-01-03 | 49.36 | USD | 3 | 12 | USD | 20.34 | 2020-01-03
386280 | 2020-01-03 | 12.83 | USD | 4 | 13 | USD | 20.34 | 2020-01-03
386283 | 2020-01-07 | 12.83 | USD | 7 | 15 | USD | 20.34 | 2020-01-03
386285 | 2020-01-11 | 12.83 | USD | 9 | | USD | 21.359 | 2020-01-09
386286 | 2020-02-12 | 62.55 | USD | 10 | | USD | 21.359 | 2020-01-09
(10 rows)
*/
Combining two tables with date ranges into one table
You can try to use JOIN
on during date and CASE WHEN
judgement the date in SELECT
clause.
SELECT T1.Range,
T1.Provider,
T1.Status,
T2.[Price Band],
CASE WHEN T1.[Valid From] >= T2.[Valid From] THEN T1.[Valid From]
ELSE T2.[Valid From] END,
CASE WHEN T1.[Valid To] <= T2.[Valid To] THEN T1.[Valid To]
ELSE T2.[Valid To] END
FROM T1 INNER JOIN T2 on
(
T1.[Valid From] between T2.[Valid From] and T2.[Valid To]
OR
T1.[Valid To] between T2.[Valid From] and T2.[Valid To]
)
AND
T1.Range =T2.Range
sqlfiddle
[Results]:
| Range | Provider | Status | Price Band | Valid From | Valid To |
|-------|----------|-----------|------------|----------------------|----------------------|
| 0113 | BT | Allocated | Price1 | 2018-01-01T00:00:00Z | 2018-06-30T23:59:59Z |
| 0113 | BT | Allocated | Price2 | 2018-07-01T00:00:00Z | 2018-07-14T23:59:59Z |
| 0113 | BT2 | Allocated | Price2 | 2018-07-15T00:00:00Z | 2299-12-31T23:59:59Z |
Related Topics
Change Colours of Particular Bars in a Bar Chart
R: Merge Two Irregular Time Series
Install Udunits2 Package for R3.3
Get a List of the Data Sets in a Particular Package
Remove Space Between Bars Ggplot2
Remove Duplicates Based on 2Nd Column Condition
How to Suppress the Creation of a Plot While Calling a Function in R
How to Get a Second Bibliography
Split a Vector by Its Sequences
Flip Ordering of Legend Without Altering Ordering in Plot
R Solve:System Is Exactly Singular
Pivot_Longer with Multiple Classes Causes Error ("No Common Type")
Dt[!(X == .)] and Dt[X != .] Treat Na in X Inconsistently
Why I Get This Error Writing Data to a File
Display Row Names in a Data.Table Object
Grouped Operations That Result in Length Not Equal to 1 or Length of Group in Dplyr