SQL Query to find the last event in a particular month - sql

I am trying to query the ID's whose last entry lies within January month (01/01/2020 to 31/01/2020).
Data is as below
ID DATE
123 25/01/2020
123 27/01/2020
123 30/01/2020
123 02/02/2020
456 17/01/2020
456 18/01/2020
456 19/01/2020
456 22/01/2020
789 30/01/2020
789 01/01/2020
654 03/01/2020
654 08/01/2020
654 10/01/2020
654 25/01/2020
Expected Output
ID DATE
456 22/01/2020
654 25/01/2020
Thank you

You can use group by and having:
select id, max(date)
from t
group by id
having max(date) >= date '2020-01-01' and
max(date) < date '2020-02-01'

Related

MySQL: How many rows have a same number as the current row has?

There is mysql Ver 15.1 Distrib 5.5.64-MariaDB, for Linux (x86_64)
table as
date number
2020-01-01 123
2020-01-02 123
2020-01-03 123
2020-01-04 123
2020-01-05 123
2020-01-07 456
2020-01-08 456
2020-01-15 456
2020-01-16 456
2020-01-07 789
2020-01-10 789
2020-01-11 789
How to get
date number count_before
2020-01-01 123 0
2020-01-02 123 1
2020-01-03 123 2
2020-01-04 123 3
2020-01-05 123 4
2020-01-07 456 0
2020-01-08 456 1
2020-01-15 456 2
2020-01-16 456 3
2020-01-07 789 0
2020-01-10 789 1
2020-01-11 789 2
where count_before is how many rows have a same number as the current row has (exclude current row)?
You can use window functions:
select
t.*,
row_number() over(partition by number order by date) - 1 count_before
from mytable t
In MariaDB < 10.3, another option is a correlated subquery:
select
t.*,
(select count(*) from mytable t1 where t1.number = t.number and t1.date < t.date) count_before
from mytable t
This query would take advantage of an index on (number, date).
You are using an old version of MariaDB. Quite old. One that doesn't support window functions.
One method uses a correlated subquery:
select t.*,
(select count(*) from t t2 where t2.number = t.number and t2.date < t.date) as count_before
from t;
With an index on (number, date) and not too many dates per number (say no more than a dozen or two), this should even have reasonable performance. Plus, the code is view-safe.

Joining two tables on a column value with sorting according to other columns

I am trying to join these two tables
Table 1
Subject_id time_x x_value
---------- ------ -------
123 12:00 4
123 15:00 3
123 19:00 2
123 21:00 1
Table 2
Subject_id time_y y_value
---------- ------- --------
123 13:00 22
123 14:00 25
123 15:00 24
123 16:00 36
123 17:00 22
123 18:00 25
123 19:00 26
123 20:00 45
on column subject_id and the result has to be like below
Result
Subject_id x_value y_value time_x time_y
---------- ------- ------- ------ ------
123 4 null 12:00 12:00
123 null 22 13:00 13:00
123 null 25 14:00 14:00
123 3 24 15:00 15:00
123 null 36 16:00 16:00
123 null 22 17:00 17:00
123 null 25 18:00 18:00
123 2 26 19:00 19:00
123 null 45 20:00 20:00
123 1 null 21:00 21:00
So can you please help me to achieve these results.
You could use a select union for obtain all the time and then left join with each table
select t.subject_id, t1.x_value, t2.y_value, t.my_time time_x, t.my_time time_y
from (
select subject_id, time_x my_time
from table1
union
select subject_id, time_y
from table2
) t
left join table1 t1 on t.subject_id = t1.subject_id
and t.my_time = t1.time_x
left join table2 t2 on t.subject_id = t2.subject_id
and t.my_time = t2.time_y
I don't see why you have two time columns. So, I think you want:
select coalesce(t1.subject_id, t2.subject_id) as subject_id,
t1.x_value, t2.y_value,
coalesce(t1.time_x, t2.time_y) as time
from table1 t1 full join
table2 t2
on t2.subject_id = t1.subject_id and t2.time_y = t1.time_x;
You can duplicate the time column if you like, but I don't think that is necessary.

HIVE SQL Collapsing continuous ranges into single rows

Consider the following records in a table:
NAME ID RATE LOC DAY
ABCD 123 -5 NYC 2017-01-01
ABCD 123 -5 NYC 2017-01-02
ABCD 123 -6 SFO 2017-01-03
ABCD 123 -6 DEN 2017-01-04
ABCD 345 -4 ATL 2017-01-05
ABCD 345 -4 WAS 2017-01-06
ABCD 123 -7 CLT 2017-01-07
ABCD 123 -7 CLT 2017-01-08
I would like to have an output like:
NAME ID RATE LOC START DAY END DAY
ABCD 123 -5 NYC 2017-01-01 2017-01-02
ABCD 123 -6 SFO 2017-01-03 2017-01-03
ABCD 123 -6 DEN 2017-01-04 2017-01-04
ABCD 345 -4 ATL 2017-01-05 2017-01-05
ABCD 345 -4 WAS 2017-01-06 2017-01-06
ABCD 123 -7 CLT 2017-01-07 2017-01-08
How do I do this in SQL or HIVE? I tried using max over partition and row_number. It doesn't seem to work. Any ideas are greatly appreciated.
This is the sql I tried:
select *
from (
select name
,id
,min(day) over (partition by name
,id) as start_date
,max(day) over (partition by name
,id) as end_date
,row_number () over (partition by name
,id
order by day asc) as row1
from table
) a
where row1=1;
This can be achieved with a difference of row numbers approach. To understand how it works, run the inner query and look at the results.
select name,id,min(day),max(day)
from (select t.*,
row_number() over(order by day)
-row_number() over(partition by name,id order by day) as grp
from tbl t
) t
group by name,id,grp

Oracle SQL query to get sales by date range

I am looking to write an SQL query that will provide me sales broken into date ranges, but it is a bit above my SQL knowledge.
I have a table of date ranges by customers as follows:
Cust Product startdate enddate
-----------------------------------
A 123 2011-01-01 2011-12-31
A 124 2011-01-01 2011-05-01
A 125 2011-01-01 2011-05-01
B 123 2011-01-01 2011-03-01
B 124 2011-01-01 2011-03-01
C 125 2011-02-02 2011-05-01
and sales stored as follows:
Cust Product date qty
-----------------------------------
A 123 2011-04-08 1
A 124 2011-01-01 12
A 125 2011-05-01 2
B 123 2011-01-04 3
B 124 2011-02-01 5
C 125 2011-03-01 80
The results should look something like:
Cust Product startdate enddate qty
-----------------------------------------
A 124 2011-01-01 2011-02-01 12
B 123 2011-01-01 2011-02-01 3
B 124 2011-02-02 2011-03-01 5
A 123 2011-03-02 2011-05-01 1
C 125 2011-03-02 2011-05-01 80
A 125 2011-05-02 2011-12-31 2
Any advice gratefully received.
I made the example in MySQL because Oracle server was down. But query is the same.
SQL Fiddle Demo
SELECT R.*, S.*
FROM dRanges R
JOIN Sales S
ON S.`date` >= R.`startdate`
AND S.`date` <= R.`enddate`
AND S.`Cust` = R.`Cust`
AND S.`Product` = R.`Product`
But you have to be carefull ranges doesnt overlap, otherwise you can have same Sales value appear on two ranges
EDIT Please explain the logic here

How do you summarize row data in sybase table

I have this table in sybase:
Date File_name File_Size customer Id
1/1/205 11:00:00 temp.csv 100000 ESPN 1111
1/1/205 11:10:00 temp.csv 200000 ESPN 1122
1/1/205 11:20:00 temp.csv 400000 ESPN 1456
1/1/205 11:30:00 temp.csv 400000 ESPN 2345
1/2/205 11:00:00 llc.csv 100000 LLC 445
1/2/205 11:10:00 llc1.txt 200000 LLC 677
1/2/205 11:20:00 dtt.txt 500000 LLC 76
1/2/205 11:30:00 jpp.txt 400000 LLC 666
I need to come up with a query to summarize this data by day which will be month/day/Year.
Date total_file_size number_of_unique_customers number_unique_id
1/1/2015 110,000 1 4
1/2/2015 120,000 1 4
How would I do this in sql query? I tried this:
select convert(varchar,arrived_at,110) as Date
sum(File_Size),
count(distinct(customer)),
count(distinct(id))
group by Date
Does not seem to be working, any ideas?
try
select
convert(varchar,arrived_at,110) as Date,
SUM(File_Size),
count(distinct customer) as number_of_unique_customers,
count(distinct id ) as number_unique_id
group by convert(varchar,arrived_at,110)