Mysql interpolation - mysql

I have the following data in mysql:
date,value,id
2016-01-01,0,1
2016-01-04,1,2
2016-01-10,2,3
2016-01-25,1,4
2016-01-26,10,5
I have another table with just dates and ids that I want to insert in the first table using the following rule: set the value as the value at the last date before the date of the given id. That is, if I have to introduce the following elements:
date,id
2016-01-02,6
2016-01-03,7
2016-01-11,8
2016-01-28,9
2016-01-28,10
I want the final table to be:
date,value,id
2016-01-01,0,1
2016-01-04,1,2
2016-01-10,2,3
2016-01-25,1,4
2016-01-26,10,5
2016-01-02,0,6
2016-01-03,0,7
2016-01-11,28
2016-01-28,10,9
2016-01-28,10,10
Can you help me please?

You can get the "previous" value using a correlated subquery:
select x.date, x.id,
(select t.value
from t
where t.date <= x.date
order by t.date desc
limit 1
) as value
from (select '2016-01-02' as date, 6 as id union all
select '2016-01-03' as date, 7 as id union all
select '2016-01-11' as date, 8 as id union all
select '2016-01-28' as date, 9 as id union all
select '2016-01-28' as date, 10 as id
) x;
If you want to insert these into the table, simply put an insert clause before the select. If you want a result set with all rows, then use union all with the other table.

Related

MYSQL - Select Only Records Where Previous Record Column Data Differs

Hoping this is possible with just sql. I have a query that returns a data set with time_stamp and hash_index columns. Basically something to the effect of:
1 1583365548 6ff11ad5536f28d66098f6d74f97d877
2 1583365554 6ff11ad5536f28d66098f6d74f97d877
3 1583365556 6ff11ad5536f28d66098f6d74f97d877
4 1583365562 a2e99acb2540d49955ef93fb2684ac25
5 1583365571 a2e99acb2540d49955ef93fb2684ac25
6 1583365572 a2e99acb2540d49955ef93fb2684ac25
7 1583365574 a2e99acb2540d49955ef93fb2684ac25
8 1583365578 a2e99acb2540d49955ef93fb2684ac25
9 1583365580 a2e99acb2540d49955ef93fb2684ac25
What I want to do is further filter this query to only include the record if the hash_index differs from the previous record. Is this something I can do without having to dump it into PHP and loop through it?
My current query is below:
SELECT
(#cnt:=#cnt + 1) AS row_number,
time_stamp,
MD5(GROUP_CONCAT(CONCAT(user_state_name,
option_id,
option_code,
item_id,
item_code))) AS hash_index
FROM
user_state
WHERE
user_id = 2
GROUP BY
time_stamp;
What is with a query like this:
SELECT t1.*
FROM user_state t1
LEFT JOIN user_state t2 ON t1.id-1 = t2.id
WHERE t1.hash_index <> t2.hash_index;
If you want to filter out adjacent duplicates, I would just use lag() and dispense with hashing and aggregation:
SELECT us.*
FROM (SELECT us.*,
LAG(time_stamp) OVER (PARTITION BY user_id ORDER BY time_stamp) as prev_ts,
LAG(time_stamp) OVER (PARTITION BY user_id, user_state_nae, option_id, option_code, item_id, item_code ORDER BY time_stamp) as prev_ts_values
FROM user_state us
WHERE user_id = 2
) t
WHERE prev_ts_values is null or prev_ts_values <> prev_ts;
You can select whichever rows you want.

Return Year-Value that occurs more than once in two columns

I would like to select all number of years that occur more than once in between two columns.
Here is what I have so far:
SELECT YEAR(`Date1`), COUNT(*) as Counter
from (SELECT YEAR(`Date1`)
from table1 UNION
SELECT YEAR(`date2`)
from table1
) as year
GROUP by YEAR(`date1`)
WHERE Counter > 2;
I appreciate any advice!
Thanks.
When you are using GROUP BY , you need to use HAVING not WHERE like following.
SELECT Y ,
COUNT(*) AS Counter
FROM (
SELECT DISTINCT YEAR(`Date1`) Y
FROM table1
UNION ALL
SELECT DISTINCT YEAR(`date2`) Y
FROM table1) AS YEAR
GROUP BY Y
HAVING COUNT(*) > 2;
Note: You don't need to put YEAR again in your outer query, also you can put DISTINCT, for each column so that you don't get duplicates for the column.
I think your problem is the UNION. It needs to be UNION ALL, or you will never find duplicates.
Then, you can simply do:
SELECT yyyy, COUNT(*) as Counter
FROM (SELECT YEAR(`Date1`) as yyyy
FROM table1
UNION ALL
SELECT YEAR(`date2`) as yyyy
FROM table1
) y
GROUP BY yyyy
HAVING Counter >= 2;
Note the changes to the query:
UNION ALL instead of UNION so the subquery does not eliminate duplicates.
Giving a column alias to the year, in this case, yyyy.
Using the column alias in the outer query.
Using HAVING instead of WHERE.

MySQL: create new table using same table twice

I want to use 1 table to create a new table using 2 sets of queries.
To test out the code: http://sqlfiddle.com/#!9/02e3ff/5
Reference table:
Desired table:
They share the same order_id.
type = A, updated_at = pDate
type = B, updated_at = dDate
Query 1:
select t.order_id, t.updated_at as pDate, weekday(t.updated_at) from transactions t
where t.type = 'A' group by t.order_id
Query 2:
select t.order_id, max(t.updated_at) as dDate, weekday(max(t.updated_at)) from transactions t
where t.type= 'B'
group by t.order_id;
For type = A, I want to get the earliest updated_at date, while for type = B, I want to get the latest updated_at date.
Currently, I tried union but they give me 2 rows instead of the desired table.
How do I join or union these 2 queries to get the desired table?
Alternatively, is there a better method to do this? Thanks!
You can try something like this:
SELECT order_id, min(pDate) pDate, max(dDate) dDate FROM(
SELECT
order_id,
if(type='A',updated_at,null) pDate,
if(type='B',updated_at,null) dDate
FROM transactions
) as d
GROUP BY order_id
SQLFiddle

Query to select duplicates in column 2 based on column 1 in MySQL

Let's say I have two columns: id and date.
I want to give it an id and it'll find all the duplicates of the value date of the column id.
Example:
id |date
1 |2013-09-16
2 |2013-09-16
3 |2013-09-23
4 |2013-09-23
I want to give it id 1 (without giving anything about date) and it'll give me a table of 2 columns listing the duplicates of id 1's date
Thanks in advance!
select * from your_table
where `date` in
(
select `date`
from your_table
where id = 1
)
or if you like to use a join
select t.*
from your_table t
inner join
(
select `date`
from your_table
where id = 1
) x on x.date = t.date

Repeat rows based on range of dates in two columns

I have a table with following columns:
ID startdate enddate
I want the rows of this table to be repeated as many times as the difference between startdate and enddate along with a column which gives all the dates between these two days for each id in the table. So, my new table should be like this:
ID Date
A startdate
A startdate +1 day
A startdate +2 days (till enddate)
B startdate
B startdate + 1 day ....
Please note that I have different start and end dates for different IDs.
I tried the answer for the following question, but this doesn't work:
Mysql select multiple rows based on one row related date range
Here's one approach.
This uses an inline view (aliased as i to generate integer values from 0 to 999, and that is joined to your table to generate up to 1000 date values, starting from startdate up to enddate for each row.
The inline view i can be easily extended to generate 10,000 or 100,000 rows, following the same pattern.
This assumes that the startdate and enddate columns are datatype DATE. (or DATETIME or TIMESTAMP or a datatype that can be implicitly converted to valid DATE values.
SELECT t.id
, t.startdate + INTERVAL i.i DAY AS `Date`
FROM ( SELECT d3.n*100 + d2.n*10 + d1.n AS i
FROM ( SELECT 0 AS n
UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3
UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6
UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9
) d1
CROSS
JOIN ( SELECT 0 AS n
UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3
UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6
UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9
) d2
CROSS
JOIN ( SELECT 0 AS n
UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3
UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6
UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9
) d3
) i
JOIN mytable t
ON i.i <= DATEDIFF(t.enddate,t.startdate)
You need a numbers table... create a temporary table or dummy table that contains the numbers 1 to X (X being the maximum possible difference between the two dates)
Then join to that table using a date diff
I'm afraid I'm SQL Server and so not sure if the datediff functions work the same way in mysql, but you should get the idea.
SELECT
DateTable.Id,
DATEADD(dd, NumbersTable.Number, DateTable.StartDate)
FROM
DateTable
INNER JOIN
NumbersTable
ON
DATEADD(dd, NumbersTable.Number, DateTable.StartDate) <= DateTable.EndDate
ORDER BY
DateTable.Id,
DATEADD(dd, NumbersTable.Number, DateTable.StartDate)
I know its very late to answer
but still one more answer using recursive cte
with recursive cte ( id, startdate) as
(
select id,startdate from test t1
union all
select t2.id,(c.startdate + interval '1 day')::date
from test t2
join cte c on c.id=t2.id and (c.startdate + interval '1 day')::date<=t2.enddate
)
select id,startdate as date from cte
order by id, startdate
its PostgreSQL specific, but it should work in other relational databases with little bit change in Date function.