I have below mentioned tables: MySQL Version - 5.7.25
Table1:
ID ref
T-1 abc-1-x
T-2 abc-2-x
T-3 abc-3-x
T-4 abc-4-x
T-5 abc-5-x
Table2
ref_id value date
abc-1-x 250 2019-12-10 14:16:19
abc-2-x 500 2019-12-11 17:21:05
abc-3-x 100 2019-12-12 18:11:01
abc-4-x 150 2019-12-13 05:04:11
abc-5-x 120 2019-12-14 12:10:09
Table3
ID seq date2
T-1 1 2019-12-10 14:05:04
T-1 2 2019-12-10 21:17:01
T-1 3 2019-12-11 13:12:12
T-2 1 2019-12-11 14:13:46
T-2 2 2019-12-12 14:05:04
T-3 1 2019-12-12 14:05:04
T-3 2 2019-12-12 17:15:14
T-3 3 2019-12-13 10:09:08
T-3 4 2019-12-14 12:18:14
T-4 1 2019-12-13 01:01:04
T-4 2 2019-12-13 03:03:01
T-5 1 2019-12-15 14:05:04
By utilizing the above mentioned three tables, I want to compare the date of Table2 with Table3 against each ID, and fetch the first date and last date from Table3 against each id.
Scenarios:
If any date of Table3 less than against particular id in Table2 show it as Less
If any date of Table3 equal to against particular id in Table2 show it as Same
If any date of Table3 greater than against particular id in Table2 show it as Greater
Required Output:
ID Value date date1 date2 remarks day_diff
T-1 250 2019-12-10 14:16:19 2019-12-10 14:05:04 2019-12-11 13:12:12 Greater 1
T-2 500 2019-12-11 17:21:05 2019-12-11 14:13:46 2019-12-12 14:05:04 Greater 1
T-3 100 2019-12-12 18:11:01 2019-12-12 14:05:04 2019-12-14 12:18:14 Greater 2
T-4 150 2019-12-13 05:04:11 2019-12-13 01:01:04 2019-12-13 03:03:01 Same 0
T-5 120 2019-12-14 12:10:09 2019-12-15 14:05:04 Null Greater 1
You can use a subquery to generate the MAX and MIN dates from Table3 for each entry in Table2 and then generate the Greater/Same/Less values in an outer query:
SELECT *,
CASE WHEN DATE(date2) > DATE(date) OR DATE(date1) > DATE(date) THEN 'Greater'
WHEN DATE(date2) < DATE(date) OR DATE(date1) < DATE(date) THEN 'Less'
ELSE 'Same'
END AS remarks,
DATEDIFF(date2, date) AS day_diff
FROM (
SELECT t3.ID, t2.Value, t2.date, MIN(t3.date2) AS date1, MAX(t3.date2) AS date2
FROM Table1 t1
JOIN Table2 t2 ON t2.ref_id = t1.ref
JOIN Table3 t3 ON t3.ID = t1.ID
GROUP BY t3.ID, t2.Value, t2.date
) g
Output:
ID Value date date1 date2 remarks day_diff
T-1 250 2019-12-10 14:16:19 2019-12-10 14:05:04 2019-12-11 13:12:12 Greater 1
T-2 500 2019-12-11 17:21:05 2019-12-11 14:13:46 2019-12-12 14:05:04 Greater 1
T-3 100 2019-12-12 18:11:01 2019-12-12 14:05:04 2019-12-14 12:18:14 Greater 2
T-4 150 2019-12-13 05:04:11 2019-12-13 01:01:04 2019-12-13 03:03:01 Same 0
T-5 120 2019-12-14 12:10:09 2019-12-15 14:05:04 2019-12-15 14:05:04 Greater 1
Note that if there is only one date for a Table2 value in Table3, this will give the same values for date1 and date2. If you really want NULL for date2 in that case, change the SELECT * in the above query to
SELECT ID, Value, date, date1,
CASE WHEN date1 = date2 THEN NULL ELSE date2 END AS date2,
Demo on dbfiddle
Related
For the life of me, can't figure out the syntax for this problem. Have two tables that I need to join into one...no problem there, but getting tripped up on the most recent date piece. Essentially, I need to iterate through each row of T1 and then find the most recent date in T2 for the same Ticker and then join the two tables together in the column structure below. Basically, showing the most recent day's information inline with the recorded day in T1.
Two mysql Tables:
T1
Ticker OpenPrice Date
AAPL 220 2019-03-01
GOOG 300 2019-03-25
AMZN 950 2019-03-17
AMZN 925 2019-03-29
AAPL 250 2019-03-07
GOOG 355 2019-03-29
T2
Ticker ClosePrice Date
AAPL 220 2019-03-02
GOOG 335 2019-03-21
AMZN 925 2019-03-24
AMZN 955 2019-03-08
AAPL 250 2019-03-18
GOOG 340 2019-03-26
TSLA 1 2019-03-04
New Joined Table Needs to Be (Column Order Doesn't Really Matter):
Ticker | OpenPrice (from T1)| Date (from T1) | ClosePrice (from T2) | Most Recent Date (from T2)
So results if joining above tables would be:
NOTE: First AAPL record in T1 wouldn't show up as there is no date before 03-01 on T2
GOOG 300 2019-03-25 335 2019-03-21
AMZN 950 2019-03-17 955 2019-03-08
AMZN 925 2019-03-29 925 2019-03-24
AAPL 250 2019-03-07 220 2019-03-02
GOOG 355 2019-03-29 340 2019-03-26
How do I solve this problem?
You can use a correlated subquery to get the date that you want:
select t1.*,
(select max(t2.date)
from t2
where t2.ticker = t1.ticker and
t2.date <= t1.date
) as t2_date
from t1;
Then, join this back to get the full record:
select . . . -- choose the columns you want
from (select t1.*,
(select max(t2.date)
from t2
where t2.ticker = t1.ticker and
t2.date <= t1.date
) as t2_date
from t1
) t1 join
t2
on t2.ticker = t1.ticker and t2.date = t1.t2_date;
I have like below mentioned two table:
Table1
ID Unique_Value
T-1 OI-45
T-4 OI-45
T-8 OI-45
T-7 OI-46
T-6 OI-49
Table2
ID Date Value
T-1 2018-01-01 15:13:22 10
T-4 2018-03-15 18:10:45 15
T-8 2018-05-12 05:17:43 25
T-7 2018-04-01 15:13:22 12
T-6 2018-06-01 15:13:22 18
I have joined the Table2 ID with Table1 ID and get the Unique_Value, based on the unique value and order by Date in Descending order and group by Unique_Value, I want to get the difference value of a particular ID from the previous Value.
Required Output would be:
ID Date Value Unique_Value Difference
T-1 2018-01-01 15:13:22 10 OI-45 [Null]
T-4 2018-03-15 18:10:45 15 OI-45 5
T-8 2018-05-12 05:17:43 25 OI-45 10
T-7 2018-04-01 15:13:22 12 OI-46 [Null]
T-6 2018-06-01 15:13:22 18 OI-49 [Null]
I have tried using Lead Log but it didn't worked.
You can try below using lag() function - it will work for mysql version 8.0+
DEMO
select id,Date,value,Unique_Value,case when prevval is null then null else value-prevval end as Difference
from
(
select t1.Id,t1.Unique_Value,t2.Date,t2.value,lag(t2.value,1) over(partition by t1.Unique_Value order by t2.Date) as prevval
from table1 t1 inner join table2 t2 on t1.id=t2.id
)A
For Mysql Version 5.7 you can try below -
DEMO
SET #quot=0, #latest=0, #comp=''
select id, Unique_Value,d,value,case when latest=1 then c=null else c end as difference
from
(
select id,Unique_Value,d,value,c,IF(#comp<>Unique_Value,1,0) as LATEST,#comp:=Unique_Value as company from
(
select t1.Id,t1.Unique_Value,value,t2.d,value-#quot as c,#quot:=value
from t1 inner join t2 on t1.id=t2.id
order by t1.Unique_Value,t2.d
)A order by Unique_Value,d
)B
OUTPUT:
id d value Unique_Value Difference
T-1 2018-01-01 10 OI-45
T-4 2018-03-15 15 OI-45 5
T-8 2018-05-12 25 OI-45 10
T-7 2018-04-01 12 OI-46
T-6 2018-06-01 18 OI-49
select a.no, a.Dtime,count(b.Dtime)+1 as Rank
from table1 a left
join table1 b on a.Dtime>b.Dtime and a.no=b.no
group by a.no,a.Dtime
order by a.no, a.Dtime
table1 Input:
NO Dtime
1 08:10:00
1 09:10:00
1 09:40:00
1 10:10:00
2 09:30:00
2 10:15:00
3 09:00:00
Output:
NO Dtime Rank
1 08:10:00 1
1 09:10:00 2
1 09:40:00 3
1 10:10:00 4
2 09:30:00 1
2 10:15:00 2
3 09:00:00 1
But I am looking for Output in mysql where table2 Rank links to table1 and table2 Dtime i.e. table1.Dtime>table2.time
table2 Input
NO Dtime
1 08:30:00
1 09:15:00
1 09:50:00
2 08:30:00
2 09:45:00
3 09:50:00
Output:
NO table1.Dtime Rank table2.Dtime
1 08:10:00 0 00:00:00
1 09:10:00 1 08:30:00
1 09:40:00 2 09:15:00
1 10:10:00 3 09:50:00
2 09:30:00 1 08:30:00
2 10:15:00 2 09:45:00
3 09:00:00 0 00:00:00
You can use the same approach with your initial query. Just left join to table2. To get the Dtime from table2 you can use a correlated subquery:
select a.no, a.Dtime,
count(b.Dtime) as Rank,
coalesce((select c.Dtime
from table2 as c
where c.no = a.no and a.Dtime > c.Dtime
order by c.Dtime desc limit 1), '00:00:00') as t2Dtime
from table1 a
left join table2 b on a.Dtime > b.Dtime and a.no = b.no
group by a.no,a.Dtime
order by a.no, a.Dtime
Demo here
I'm trying to group my data by 7 days interval.
for example.
I have a data which is you can find it below.
count startDate finish_date
1247 2017-03-09 08:43:18 2017-03-09 16:05:34
1681 2017-03-10 08:30:13 2017-03-10 16:31:55
1464 2017-03-11 08:36:50 2017-03-11 16:42:03
1343 2017-03-12 08:26:57 2017-03-12 16:39:58
1333 2017-03-13 08:35:34 2017-03-13 16:26:18
1215 2017-03-14 08:36:58 2017-03-14 16:13:20
1817 2017-03-16 08:24:49 2017-03-16 17:18:19
1675 2017-03-17 08:22:30 2017-03-17 16:36:58
1546 2017-03-18 08:33:52 2017-03-18 16:51:52
1443 2017-03-20 08:11:00 2017-03-20 16:26:38
1481 2017-03-21 08:26:04 2017-03-21 16:57:30
1574 2017-03-23 08:19:07 2017-03-23 16:12:46
1270 2017-03-24 08:25:25 2017-03-24 16:37:59
1765 2017-03-25 08:22:58 2017-03-25 16:44:24
1200 2017-03-26 08:37:47 2017-03-26 14:59:51
1479 2017-03-27 08:17:50 2017-03-27 15:18:32
And I wanted to group them by 7 days interval.
I tried this. for it.
select count(*), min(locationDate) as startDate, max(locationDate) as finish_date from location where tagCode = 24901 and xLocation >= 278 and xLocation <= 354 and yLocation >= 239 and yLocation <= 426 and locationDate
>= DATE_SUB('2017-03-01 00:00:01',INTERVAL 7 day) and locationDate <= '2017-03-27 23:59:59' group by DATEDIFF(locationDate, '2017-03-01 00:00:01') div 7
And data is like.
count startDate finish_date
8283 2017-03-09 08:43:18 2017-03-14 16:13:20
7962 2017-03-16 08:24:49 2017-03-21 16:57:30
7291 2017-03-23 08:19:07 2017-03-27 15:22:05
Problem is Second Week it must start from 2017-03-15 and third week need to start 2017-03-22 but because of there is no data in on days its not starting how can I fix it ?
As I asked you in my comment, I think the result you wrote would be good with the input you provided, but it wouldn't be with a different input (like having 2017-03-15 but not 2017-03-16).
A solution could be to write the query kind of like this
select sum(count) as count, min(location_date), max(location_date)
from (
select t1.location_date,
t1.count,
date_sub(location_date, interval (datediff(t1.location_date, t2.min_date) % 7) day) week_start
from location t1
cross join
(select min(location_date) as min_date from location) t2
where t1.tagCode = 24901 and
t1.xLocation between 278 and 354 and
t1.yLocation between 239 and 426 and
t1.locationDate >= DATE_SUB('2017-03-01 00:00:01',INTERVAL 7 day) and
t1.locationDate <= '2017-03-27 23:59:59'
) t3
group by week_start
I tested a simplified version of this on a simplified version of your input, there might be typos...
Edit
To display both interval starting date and ending date, try with this
select sum(count) as count, week_start, week_end
from (
select t1.count,
date_sub(location_date, interval (datediff(t1.location_date, t2.min_date) % 7) day) week_start,
date_sub(location_date, interval (datediff(t1.location_date, t2.min_date) % 7) - 6 day) week_end
from location t1
cross join
(select min(location_date) as min_date from location) t2
where t1.tagCode = 24901 and
t1.xLocation between 278 and 354 and
t1.yLocation between 239 and 426 and
t1.locationDate >= DATE_SUB('2017-03-01 00:00:01',INTERVAL 7 day) and
t1.locationDate <= '2017-03-27 23:59:59'
) t3
group by week_start, week_end
I just use GROUP BY DATE_FORMAT:
SELECT someTimeStamp,SUM(amount) AS Total FROM sometable WHERE 1 GROUP BY DATE_FORMAT(someTimeStamp,"%Y%v")
I think you can do that :
you need to change the result of your query from this :
1 1247 2017-03-09 08:43:18 2017-03-09 16:05:34
2 1681 2017-03-10 08:30:13 2017-03-10 16:31:55
3 1464 2017-03-11 08:36:50 2017-03-11 16:42:03
4 1343 2017-03-12 08:26:57 2017-03-12 16:39:58
5 1333 2017-03-13 08:35:34 2017-03-13 16:26:18
6 1215 2017-03-14 08:36:58 2017-03-14 16:13:20
7 1817 2017-03-16 08:24:49 2017-03-16 17:18:19
8 1675 2017-03-17 08:22:30 2017-03-17 16:36:58
9 1546 2017-03-18 08:33:52 2017-03-18 16:51:52
10 1443 2017-03-20 08:11:00 2017-03-20 16:26:38
11 1481 2017-03-21 08:26:04 2017-03-21 16:57:30
12 1574 2017-03-23 08:19:07 2017-03-23 16:12:46
13 1270 2017-03-24 08:25:25 2017-03-24 16:37:59
14 1765 2017-03-25 08:22:58 2017-03-25 16:44:24
15 1200 2017-03-26 08:37:47 2017-03-26 14:59:51
16 1479 2017-03-27 08:17:50 2017-03-27 15:18:32
to This using the logic of computing the number of days between the max date and the min date of the first line :
-- max date of the row min date of the first row
select FLOOR(datediff('2017-03-12 16:05:34', '2017-03-09 08:43:18')/7);
select FLOOR( datediff('2017-03-16 17:18:19', '2017-03-09 08:43:18')/7);
-- what is important that you always compute the max date - the min date of the first row the same row like in your example is : '2017-03-09 08:43:18'
select FLOOR( datediff(max_date, '2017-03-09 08:43:18')/7);
rec_sum min_date max_date day_diff
1 1247 2017-03-09 08:43:18 2017-03-09 16:05:34 0
2 1681 2017-03-10 08:30:13 2017-03-10 16:31:55 0
3 1464 2017-03-11 08:36:50 2017-03-11 16:42:03 0
4 1343 2017-03-12 08:26:57 2017-03-12 16:39:58 0
5 1333 2017-03-13 08:35:34 2017-03-13 16:26:18 0
6 1215 2017-03-14 08:36:58 2017-03-14 16:13:20 0
7 1817 2017-03-16 08:24:49 2017-03-16 17:18:19 1
8 1675 2017-03-17 08:22:30 2017-03-17 16:36:58 1
9 1546 2017-03-18 08:33:52 2017-03-18 16:51:52 1
10 1443 2017-03-20 08:11:00 2017-03-20 16:26:38 1
11 1481 2017-03-21 08:26:04 2017-03-21 16:57:30 1
12 1574 2017-03-23 08:19:07 2017-03-23 16:12:46 2
13 1270 2017-03-24 08:25:25 2017-03-24 16:37:59 2
14 1765 2017-03-25 08:22:58 2017-03-25 16:44:24 2
15 1200 2017-03-26 08:37:47 2017-03-26 14:59:51 2
16 1479 2017-03-27 08:17:50 2017-03-27 15:18:32 2
-- now you can group the new result by the new field the result of division.
select
sum(rec_sum) ,
min(min_date),
max(max_date)
from (query result in the previous list)
group by day_diff
i know it's a little bit hard but i think you can do it the hard way is the day_diff computing .
I have on table, that I record Car#,Date,RunHours as bellow:
Car# Date RunHours
125 2014-01-01 1250
125 2014-02-10 3250
215 2014-02-11 1400
215 2014-03-01 1800
125 2014-03-15 4100
215 2014-04-10 2500
I need the select result as bellow:
Car# Date Runhours Previous_Date Previous_RunHours
125 2014-01-01 1250 N/A N/A
125 2014-02-10 3250 2014-01-01 1250
215 2014-02-11 1400 N/A N/A
215 2014-03-01 1800 2014-02-11 1400
125 2014-03-15 4100 2014-02-10 3250
215 2014-04-10 2500 2014-02-11 1800
How can I do it.
Here is one method, using correlated subqueries to get the previous information:
select t.*,
(select t2.date
from table t2
where t2.car = t.car and t2.date < t.date
order by t2.date desc
limit 1
) as prev_date,
(select t2.runhours
from table t2
where t2.car = t.car and t2.date < t.date
order by t2.date desc
limit 1
) as prev_runhours
from table t;
For performance, you want an index on table(car, date).