Add value from one table to another, depending on dates - sql

how can i add a value from one table to another. There is a attribute(VALUE) that depends on the date from both tables. So VALUE has to get add to TABLE 1 between the corret dates.
Example:
Table 1
ID BEGIN END MODEL DOLLAR
1 2014-01-01 2014-01-31 Z5 500
1 2014-02-01 2014-02-28 Z5 500
1 2014-03-01 2014-03-31 Z5 672
1 2014-03-11 2014-03-31 Z3 158
1 2014-04-01 2014-04-30 Z3 023
....
1 2016-12-01 2016-12-31 Z2 400
1 2017-01-01 2017-01-31 Z4 433
1 2017-02-01 2017-02-28 Z9 065
Table 2
ID BEGIN END VALUE
1 2014-01-01 2017-01-01 3
1 2017-01-01 2999-12-31 9
This is a small example from 2 big tables. I discovered that the join works, but sometimes some errors occurs(because sum(dollar) isnt 100% right). Do i have to add something in the join clause?
select * from t1
INNER JOIN t2 on
(
t1.id = t2.id
and t1.begin between t2.beginn and t1.begin
and t1.end between t1.end and t2.end
)
DESIRED RESULT
ID BEGIN END MODEL DOLLAR VALUE
1 2014-01-01 2014-01-31 Z5 500 3
1 2014-02-01 2014-02-28 Z5 500 3
1 2014-03-01 2014-03-31 Z5 672 3
1 2014-03-11 2014-03-31 Z3 158 3
1 2014-04-01 2014-04-30 Z3 023 3
...
1 2016-12-01 2016-12-31 Z2 400 3
1 2017-01-01 2017-01-31 Z4 433 9
1 2017-02-01 2017-02-28 Z9 065 9

If you want any overlap, then:
select *
from t1 join
t2
on t1.id = t2.id and
t2.begin <= t1.end
t2.end >= t1.begin;
If you want full overlap then:
select *
from t1 join
t2
on t1.id = t2.id and
t2.begin <= t1.begin
t2.end >= t1.end;
Note: Because you are dealing with time ranges, you may get multiple matches in the result set for a single time frame.

Related

Get all rows from one table stream and the row before in time from an other table

Suppose I have one table (table_1) and one table stream (stream_1) that gets changes made to table_1, in my case only inserts of new rows. And once I have acted on these changes, the rowes will be removed from stream_1 but remain in table_1.
From that I would like to calculate delta values for var1 (var1 - lag(var1) as delta_var1) partitioned on a customer and just leave var2 as it is. So the data in table_1 could look something like this:
timemessage
customerid
var1
var2
2021-04-01 06:00:00
1
10
5
2021-04-01 07:00:00
2
100
7
2021-04-01 08:00:00
1
20
10
2021-04-01 09:00:00
1
40
3
2021-04-01 15:00:00
2
150
5
2021-04-01 23:00:00
1
50
6
2021-04-02 06:00:00
2
180
2
2021-04-02 07:00:00
1
55
9
2021-04-02 08:00:00
2
200
4
And the data in stream_1 that I want to act on could looks like this:
timemessage
customerid
var1
var2
2021-04-01 23:00:00
1
50
6
2021-04-02 06:00:00
2
180
2
2021-04-02 07:00:00
1
55
9
2021-04-02 08:00:00
2
200
4
But to be able to calculate delta_var1 for all customers I would need the previous row in time for each customer before the ones in stream_1.
For example: To be able to calculate how much var1 has increased for customerid = 1 between 2021-04-01 09:00:00 and 2021-04-01 23:00:00 I want to include the 2021-04-01 09:00:00 row for customerid = 1 in my output.
So I would like to create a select containing all rows in stream_1 + the previous row in time for each customerid from table_1: The wanted output is the following in regard to the mentioned table_1 and stream_1.
timemessage
customerid
var1
var2
2021-04-01 09:00:00
1
40
3
2021-04-01 15:00:00
2
150
5
2021-04-01 23:00:00
1
50
6
2021-04-02 06:00:00
2
180
2
2021-04-02 07:00:00
1
55
9
2021-04-02 08:00:00
2
200
4
So given you have the "last value per day" in your wanted output, you are want a QUALIFY to keep only the wanted rows and using ROW_NUMBER partitioned by customerid and timemessage. Assuming the accumulator it positive only you can order by accumulatedvalue thus:
WITH data(timemessage, customerid, accumulatedvalue) AS (
SELECT * FROM VALUES
('2021-04-01', 1, 10)
,('2021-04-01', 2, 100)
,('2021-04-02', 1, 20)
,('2021-04-03', 1, 40)
,('2021-04-03', 2, 150)
,('2021-04-04', 1, 50)
,('2021-04-04', 2, 180)
,('2021-04-05', 1, 55)
,('2021-04-05', 2, 200)
)
SELECT * FROM data
QUALIFY ROW_NUMBER() OVER (PARTITION BY customerid,timemessage ORDER BY accumulatedvalue DESC) = 1
ORDER BY 1,2;
gives:
TIMEMESSAGE CUSTOMERID ACCUMULATEDVALUE
2021-04-01 1 10
2021-04-01 2 100
2021-04-02 1 20
2021-04-03 1 40
2021-04-03 2 150
2021-04-04 1 50
2021-04-04 2 180
2021-04-05 1 55
2021-04-05 2 200
if you can trust your data and data in table2 starts right after data in table1 then you can just get the last records for each customer from table1 and union with table2:
select * from table1
qualify row_number() over (partitioned by customerid order by timemessage desc) = 1
union all
select * from table2
if not
select a.* from table1 a
join table2 b
on a.customerid = b.customerid
and a.timemessage < b.timemessage
qualify row_number() over (partitioned by a.customerid order by a.timemessage desc) = 1
union all
select * from table2
also you can add a condition to not look to data for more than 1 day (or 1 hour or whatever safe interval is to look at) for better performance

Join two table by dates and populate the missing data when one table has missing dates

In SQL Server, I have a two tables (tbl1 and tbl2) as shown below. tbl2 contains a list of all dates. In tbl1, some of the dates are missing.
tbl1
name nameid count date
-----------------------------------------------
apple 1 77 2019-07-29 00:00:00.000
orange 2 129 2019-07-29 00:00:00.000
apple 1 399 2019-08-05 00:00:00.000
orange 2 27 2019-08-05 00:00:00.000
apple 1 122 2019-08-12 00:00:00.000
orange 2 5 2019-08-19 00:00:00.000
tbl2
timeid date
5 2019-07-29 00:00:00.000
4 2019-08-05 00:00:00.000
3 2019-08-12 00:00:00.000
2 2019-08-19 00:00:00.000
1 2019-08-26 00:00:00.000
What I need is the table below. I need to join the two table, populate the name and nameid for the missing dates, and set those counts as 0.
date name nameid count timeid
---------------------------------------------------
2019-07-29 00:00:00.000 apple 1 77 5
2019-07-29 00:00:00.000 orange 2 129 5
2019-08-05 00:00:00.000 apple 1 399 4
2019-08-05 00:00:00.000 orange 2 27 4
2019-08-12 00:00:00.000 apple 1 122 3
2019-08-12 00:00:00.000 orange 2 0 3
2019-08-19 00:00:00.000 apple 1 0 2
2019-08-19 00:00:00.000 orange 2 5 2
2019-08-26 00:00:00.000 apple 1 0 1
2019-08-26 00:00:00.000 orange 2 0 1
I did the following:
SELECT t1.date, name, nameid, count, timeid
FROM tbl2 t1
LEFT JOIN tbl1 t2 ON t1.date = t2.date
and got this output:
date name nameid count timeid
----------------------------------------------------------
2019-07-29 00:00:00.000 apple 1 77 5
2019-07-29 00:00:00.000 orange 2 129 5
2019-08-05 00:00:00.000 apple 1 399 4
2019-08-05 00:00:00.000 orange 2 27 4
2019-08-12 00:00:00.000 apple 1 122 3
2019-08-19 00:00:00.000 orange 2 5 2
2019-08-26 00:00:00.000 NULL NULL NULL 1
It does not seem to be right. Does anyone know how I can generate the desired joined table?
Below is the code to generate tbl1 and tbl2
DROP TABLE IF EXISTS tbl1
CREATE TABLE tbl1
(
name VARCHAR (50) NOT NULL,
nameid INT NOT NULL,
count INT NOT NULL,
date DATETIME
);
INSERT INTO tbl1(name, nameid, count, date)
VALUES ('apple', 1, 77, '2019-07-29'),
('orange', 2, 129, '2019-07-29'),
('apple', 1, 399, '2019-08-05'),
('orange', 2, 27, '2019-08-05'),
('apple', 1, 122, '2019-08-12'),
('orange', 2, 5, '2019-08-19');
DROP TABLE IF EXISTS tbl2
CREATE TABLE tbl2
(
timeid INT NOT NULL,
date DATETIME
);
INSERT INTO tbl2(timeid, date)
VALUES (5,'2019-07-29'),
(4,'2019-08-05'),
(3,'2019-08-12'),
(2,'2019-08-19'),
(1,'2019-08-26');
To achieve your desired result, you need to cross join the distinct name values from tbl1 with the dates from tbl2 and then LEFT JOIN that to tbl1 again, using COALESCE to replace NULL values of count with 0:
SELECT t2.date, n.name, n.nameid, COALESCE(t1.count, 0) AS count, t2.timeid
FROM tbl2 t2
CROSS APPLY (SELECT DISTINCT name, nameid FROM tbl1) n
LEFT JOIN tbl1 t1 ON t1.date = t2.date AND t1.name = n.name
ORDER BY t2.date, n.name
Output:
date name nameid count timeid
2019-07-29 00:00:00.000 apple 1 77 5
2019-07-29 00:00:00.000 orange 2 129 5
2019-08-05 00:00:00.000 apple 1 399 4
2019-08-05 00:00:00.000 orange 2 27 4
2019-08-12 00:00:00.000 apple 1 122 3
2019-08-12 00:00:00.000 orange 2 0 3
2019-08-19 00:00:00.000 apple 1 0 2
2019-08-19 00:00:00.000 orange 2 5 2
2019-08-26 00:00:00.000 apple 1 0 1
2019-08-26 00:00:00.000 orange 2 0 1
Demo on dbfiddle

SQL Server : compare rows, exclude from results when some values are the same

I have the following SQL Server query problem.
If there is a row where Issue_DATE = as Maturity_Date in another row, and if both rows have the same ID and Amount USD, then none of these rows should be displayed.
Here is a simplified version of my table:
ID ISSUE_DATE MATURITY_DATE AMOUNT_USD
1 2010-01-01 00:00:00.000 2015-12-01 00:00:00.000 5000
1 2010-01-01 00:00:00.000 2001-09-19 00:00:00.000 700
2 2014-04-09 00:00:00.000 2019-04-09 00:00:00.000 400
1 2015-12-01 00:00:00.000 2016-12-31 00:00:00.000 5000
5 2015-02-24 00:00:00.000 2015-02-24 00:00:00.000 8000
4 2012-11-29 00:00:00.000 2015-11-29 00:00:00.000 10000
3 2015-01-21 00:00:00.000 2018-01-21 00:00:00.000 17500
2 2015-02-02 00:00:00.000 2015-12-05 00:00:00.000 12000
1 2015-01-12 00:00:00.000 2018-01-12 00:00:00.000 18000
2 2015-12-05 00:00:00.000 2016-01-10 00:00:00.000 12000
Result should be:
ID ISSUE_DATE MATURITY_DATE AMOUNT_USD
1 2010-01-01 00:00:00.000 2001-09-19 00:00:00.000 700
2 2014-04-09 00:00:00.000 2019-04-09 00:00:00.000 400
5 2015-02-24 00:00:00.000 2015-02-24 00:00:00.000 8000
4 2012-11-29 00:00:00.000 2015-11-29 00:00:00.000 10000
3 2015-01-21 00:00:00.000 2018-01-21 00:00:00.000 17500
1 2015-01-12 00:00:00.000 2018-01-12 00:00:00.000 18000
I tried with self join, but I do not get right result.
Thanks in advance!
Can you try something like this? 'not exists' is the way of doing it.
select * from table t1 where not exists (select 'x' from table t2 where t1.issue_date = t2.maturity_date and t1.amount_usd=t2.amount_usd and t1.id = t2.id)
I'd think about making subquery of all the dupes and then eliminating them from the first table like so:
select t1.ID
, t1.ISSUE_DATE
, t1.MATURITY_DATE
, t1.AMOUNT_USD
FROM
t1
LEFT JOIN
(select a.ID
, a.ISSUE_DATE
, a.MATURITY_DATE
, a.AMOUNT_USD
FROM
t1 a
INNER JOIN
ti b
) dupes
on
t1.ID = dupes.ID
WHERE dupes.ID IS NULL;

SQL Date Range Query - Table Comparison

I have two SQL Server tables containing the following information:
Table t_venues:
venue_id is unique
venue_id | start_date | end_date
1 | 01/01/2014 | 02/01/2014
2 | 05/01/2014 | 05/01/2014
3 | 09/01/2014 | 15/01/2014
4 | 20/01/2014 | 30/01/2014
Table t_venueuser:
venue_id is not unique
venue_id | start_date | end_date
1 | 02/01/2014 | 02/01/2014
2 | 05/01/2014 | 05/01/2014
3 | 09/01/2014 | 10/01/2014
4 | 23/01/2014 | 25/01/2014
From these two tables I need to find the dates that haven't been selected for each range, so the output would look like this:
venue_id | start_date | end_date
1 | 01/01/2014 | 01/01/2014
3 | 11/01/2014 | 15/01/2014
4 | 20/01/2014 | 22/01/2014
4 | 26/01/2014 | 30/01/2014
I can compare the two tables and get the date ranges from t_venues to appear in my query using 'except' but I can't get the query to produce the non-selected dates. Any help would be appreciated.
Calendar Table!
Another perfect candidate for a calendar table. If you can't be bothered to search for one, here's one I made earlier.
Setup Data
DECLARE #t_venues table (
venue_id int
, start_date date
, end_date date
);
INSERT INTO #t_venues (venue_id, start_date, end_date)
VALUES (1, '2014-01-01', '2014-01-02')
, (2, '2014-01-05', '2014-01-05')
, (3, '2014-01-09', '2014-01-15')
, (4, '2014-01-20', '2014-01-30')
;
DECLARE #t_venueuser table (
venue_id int
, start_date date
, end_date date
);
INSERT INTO #t_venueuser (venue_id, start_date, end_date)
VALUES (1, '2014-01-02', '2014-01-02')
, (2, '2014-01-05', '2014-01-05')
, (3, '2014-01-09', '2014-01-10')
, (4, '2014-01-23', '2014-01-25')
;
The Query
SELECT t_venues.venue_id
, calendar.the_date
, CASE WHEN t_venueuser.venue_id IS NULL THEN 1 ELSE 0 END As is_available
FROM dbo.calendar /* see: http://gvee.co.uk/files/sql/dbo.numbers%20&%20dbo.calendar.sql for an example */
INNER
JOIN #t_venues As t_venues
ON t_venues.start_date <= calendar.the_date
AND t_venues.end_date >= calendar.the_date
LEFT
JOIN #t_venueuser As t_venueuser
ON t_venueuser.venue_id = t_venues.venue_id
AND t_venueuser.start_date <= calendar.the_date
AND t_venueuser.end_date >= calendar.the_date
ORDER
BY t_venues.venue_id
, calendar.the_date
;
The Result
venue_id the_date is_available
----------- ----------------------- ------------
1 2014-01-01 00:00:00.000 1
1 2014-01-02 00:00:00.000 0
2 2014-01-05 00:00:00.000 0
3 2014-01-09 00:00:00.000 0
3 2014-01-10 00:00:00.000 0
3 2014-01-11 00:00:00.000 1
3 2014-01-12 00:00:00.000 1
3 2014-01-13 00:00:00.000 1
3 2014-01-14 00:00:00.000 1
3 2014-01-15 00:00:00.000 1
4 2014-01-20 00:00:00.000 1
4 2014-01-21 00:00:00.000 1
4 2014-01-22 00:00:00.000 1
4 2014-01-23 00:00:00.000 0
4 2014-01-24 00:00:00.000 0
4 2014-01-25 00:00:00.000 0
4 2014-01-26 00:00:00.000 1
4 2014-01-27 00:00:00.000 1
4 2014-01-28 00:00:00.000 1
4 2014-01-29 00:00:00.000 1
4 2014-01-30 00:00:00.000 1
(21 row(s) affected)
The Explanation
Our calendar tables contains an entry for every date.
We join our t_venues (as an aside, if you have the choice, lose the t_ prefix!) to return every day between our start_date and end_date. Example output for venue_id=4 for just this join:
venue_id the_date
----------- -----------------------
4 2014-01-20 00:00:00.000
4 2014-01-21 00:00:00.000
4 2014-01-22 00:00:00.000
4 2014-01-23 00:00:00.000
4 2014-01-24 00:00:00.000
4 2014-01-25 00:00:00.000
4 2014-01-26 00:00:00.000
4 2014-01-27 00:00:00.000
4 2014-01-28 00:00:00.000
4 2014-01-29 00:00:00.000
4 2014-01-30 00:00:00.000
(11 row(s) affected)
Now we have one row per day, we [outer] join our t_venueuser table. We join this in much the same manner as before, but with one added twist: we need to join based on the venue_id too!
Running this for venue_id=4 gives this result:
venue_id the_date t_venueuser_venue_id
----------- ----------------------- --------------------
4 2014-01-20 00:00:00.000 NULL
4 2014-01-21 00:00:00.000 NULL
4 2014-01-22 00:00:00.000 NULL
4 2014-01-23 00:00:00.000 4
4 2014-01-24 00:00:00.000 4
4 2014-01-25 00:00:00.000 4
4 2014-01-26 00:00:00.000 NULL
4 2014-01-27 00:00:00.000 NULL
4 2014-01-28 00:00:00.000 NULL
4 2014-01-29 00:00:00.000 NULL
4 2014-01-30 00:00:00.000 NULL
(11 row(s) affected)
See how we have a NULL value for rows where there is no t_venueuser record. Genius, no? ;-)
So in my first query I gave you a quick CASE statement that shows availability (1=available, 0=not available). This is for illustration only, but could be useful to you.
You can then either wrap the query up and then apply an extra filter on this calculated column or simply add a where clause in: WHERE t_venueuser.venue_id IS NULL and that will do the same trick.
This is a complete hack, but it gives the results you require, I've only tested it on the data you provided so there may well be gotchas with larger sets.
In general what you are looking at solving here is a variation of gaps and islands problem ,this is (briefly) a sequence where some items are missing. The missing items are referred as gaps and the existing items are referred as islands. If you would like to understand this issue in general check a few of the articles:
Simple talk article
blogs.MSDN article
SO answers tagged gaps-and-islands
Code:
;with dates as
(
SELECT vdates.venue_id,
vdates.vdate
FROM ( SELECT DATEADD(d,sv.number,v.start_date) vdate
, v.venue_id
FROM t_venues v
INNER JOIN master..spt_values sv
ON sv.type='P'
AND sv.number BETWEEN 0 AND datediff(d, v.start_date, v.end_date)) vdates
LEFT JOIN t_venueuser vu
ON vdates.vdate >= vu.start_date
AND vdates.vdate <= vu.end_date
AND vdates.venue_id = vu.venue_id
WHERE ISNULL(vu.venue_id,-1) = -1
)
SELECT venue_id, ISNULL([1],[2]) StartDate, [2] EndDate
FROM (SELECT venue_id, rDate, ROW_NUMBER() OVER (PARTITION BY venue_id, DateType ORDER BY rDate) AS rType, DateType as dType
FROM( SELECT d1.venue_id
,d1.vdate AS rDate
,'1' AS DateType
FROM dates AS d1
LEFT JOIN dates AS d0
ON DATEADD(d,-1,d1.vdate) = d0.vdate
LEFT JOIN dates AS d2
ON DATEADD(d,1,d1.vdate) = d2.vdate
WHERE CASE ISNULL(d2.vdate, '01 Jan 1753') WHEN '01 Jan 1753' THEN '2' ELSE '1' END = 1
AND ISNULL(d0.vdate, '01 Jan 1753') = '01 Jan 1753'
UNION
SELECT d1.venue_id
,ISNULL(d2.vdate,d1.vdate)
,'2'
FROM dates AS d1
LEFT JOIN dates AS d2
ON DATEADD(d,1,d1.vdate) = d2.vdate
WHERE CASE ISNULL(d2.vdate, '01 Jan 1753') WHEN '01 Jan 1753' THEN '2' ELSE '1' END = 2
) res
) src
PIVOT (MIN (rDate)
FOR dType IN
( [1], [2] )
) AS pvt
Results:
venue_id StartDate EndDate
1 2014-01-01 2014-01-01
3 2014-01-11 2014-01-15
4 2014-01-20 2014-01-22
4 2014-01-26 2014-01-30

Joining records from same table

There is a table test that contains data as shown below:
id id1 id2 id3 date1
1 1 2 2500 2010-09-30 00:00:00.000
2 1 2 4700 2005-01-01 00:00:00.000
3 1 2 4700 2009-08-01 00:00:00.000
4 1 3 2500 2010-09-30 00:00:00.000
5 1 3 4700 2003-02-01 00:00:00.000
6 1 8 4000 2007-04-01 00:00:00.000
7 1 8 4000 2013-09-01 00:00:00.000
8 1 8 4060 2007-04-01 00:00:00.000
9 1 8 8500 2010-09-30 00:00:00.000
What I need to do is order this data in the following format:
id1 id2 id3 date1 date2
1 2 2500 2010-09-30 00:00:00.000 9999-12-31 23:59:59.997
1 2 4700 2005-01-01 00:00:00.000 2009-07-31 00:00:00.000
1 2 4700 2009-08-01 00:00:00.000 9999-12-31 23:59:59.997
1 3 2500 2010-09-30 00:00:00.000 9999-12-31 23:59:59.997
1 3 4700 2003-02-01 00:00:00.000 9999-12-31 23:59:59.997
1 8 4000 2007-04-01 00:00:00.000 2013-08-31 00:00:00.000
1 8 4000 2013-09-01 00:00:00.000 9999-12-31 23:59:59.997
1 8 4060 2007-04-01 00:00:00.000 9999-12-31 23:59:59.997
1 8 8500 2010-09-30 00:00:00.000 9999-12-31 23:59:59.997
Using the following logic:
If there is only one record for the same id1, id2 and id3 we use the original date for date1 and we use the maximum date available in sql server (9999-12-31) for date2.
If there is more than one record for the same id1, id2 and id3 we still keep the original date for date1 and we use for date2 the original date field minus 1 day from the next record . The last record will use also the maximum date available in sql server (9999-12-31) for date2.
I manage to build the following query but it is not perfect as it brings some invalid records:
select * from
(select
t1.id1,t1.id2,t1.id3,t1.date1,
case
when t1.date1=t2.date1 then CONVERT(DATETIME, '12/31/9999 23:59:59.997')
else DATEADD(day, -1, t2.date1)
end as date2
from test t1
inner join test t2
on t1.id1=t2.id1 and t1.id2=t2.id2 and t1.id3=t2.id3
) sub
where date2>=date1
order by id1,id2,id3,date1 asc
The result of the query is:
id1 id2 id3 date1 date2
1 2 2500 2010-09-30 00:00:00.000 9999-12-31 23:59:59.997
1 2 4700 2005-01-01 00:00:00.000 9999-12-31 23:59:59.997 *
1 2 4700 2005-01-01 00:00:00.000 2009-07-31 00:00:00.000
1 2 4700 2009-08-01 00:00:00.000 9999-12-31 23:59:59.997
1 3 2500 2010-09-30 00:00:00.000 9999-12-31 23:59:59.997
1 3 4700 2003-02-01 00:00:00.000 9999-12-31 23:59:59.997
1 8 4000 2007-04-01 00:00:00.000 9999-12-31 23:59:59.997 *
1 8 4000 2007-04-01 00:00:00.000 2013-08-31 00:00:00.000
1 8 4000 2013-09-01 00:00:00.000 9999-12-31 23:59:59.997
1 8 4060 2007-04-01 00:00:00.000 9999-12-31 23:59:59.997
1 8 8500 2010-09-30 00:00:00.000 9999-12-31 23:59:59.997
As you can see, the records marked with * are not necessary but I don't know how to get rid off that rows.
This should do:
select id1,id2,id3, date1,
isnull(lead(date1) over(partition by id1,id2,id3 order by date1)-1, '99991231') as date2
from test
Try something like this
SELECT t1.id1, t1.id2, t1.id3, t1.date1 as date1,
ISNULL(t2.date1, CONVERT(DATETIME, '12/31/9999 23:59:59.997')) as date2
FROM test t1
LEFT JOIN test t2 ON t1.id1 = t2.id1 AND t1.id2 = t2.id2 AND t1.id3 = t2.id3
AND t1.id < t2.id
ORDER BY t1.id1, t1.id2, t1.id3, date1, date2