Given the following table with purchase data.
CREATE TABLE myTable (
id INT NOT NULL AUTO_INCREMENT,
date DATETIME NOT NULL,
subNo SMALLINT NOT NULL,
poNo INT NOT NULL,
PRIMARY KEY (id))
INSERT INTO myTable VALUES (0, '2022-11-01 12:43', 1, 800), (0, '2022-11-02 13:00', 1, 800), (0, '2022-11-03 12:43', 2, 800), (0, '2022-11-03 14:00', 1, 923), (0, '2022-11-03 15:00', 2, 800), (0, '2022-11-04 12:43', 1, 800)
Id | Date | SubNo | PO# |
----|------------------|-------|-----|
100 | 2022-11-01 12:43 | 1 | 800 |
101 | 2022-11-02 13:00 | 1 | 800 |
102 | 2022-11-03 12:43 | 2 | 800 |
103 | 2022-11-03 14:00 | 1 | 923 |
104 | 2022-11-03 15:00 | 2 | 800 |
105 | 2022-11-04 12:43 | 1 | 800 |
SubNo is the ordinal number of a subset or partial quantity of the purchase (PO#). There can be more than 30 subsets to a purchase.
I am looking for a query supplying for a given purchase for each of its subsets the latest date.
For PO 800 it would look like this:
Id | Date | SubNo | PO# |
----|------------------|-------|-----|
105 | 2022-11-04 12:43 | 1 | 800 |
104 | 2022-11-03 15:00 | 2 | 800 |
I haven't found a way to filter the latest dates.
A rough approach is
SELECT id, date, subNo
FROM myTable
WHERE poNo=800
GROUP BY subNo
ORDER BY subNo, date DESC
but DISTINCT and GROUP BY do not guarantee to return the latest date.
Then I tried to create a VIEW first, to be used in a later query.
CREATE VIEW myView AS
SELECT subNo s, (SELECT MAX(date) FROM myTable WHERE poNo=800 AND subNo=s) AS dd
FROM myTable
WHERE poNo=800
GROUP BY s
But although the query is ok, the result differs when used for a VIEW, probably due to VIEW restrictions.
Finally I tried a joined table
SELECT id, datum, subNo s
FROM myTable my JOIN (SELECT MAX(date) AS d FROM myTable WHERE poNo=800 AND subNo=s) tmp ON my.date=tmp.d
WHERE poNo=800
but getting the error "Unknown column 's' in where clause.
My MySql version is 8.0.22
You can check if (date, subno) corresponds to one of the pairs of ( MAX(date), subno) :
SELECT id, date, subno
FROM mytable
WHERE pono = 800 AND (date, subno) IN (
SELECT MAX(date), subno
FROM mytable
WHERE pono = 800
GROUP BY subno
)
GROUP BY subno;
My result in a clean table :
+----+---------------------+-------+
| id | date | subno |
+----+---------------------+-------+
| 6 | 2022-11-04 12:43:00 | 1 |
| 5 | 2022-11-03 15:00:00 | 2 |
+----+---------------------+-------+
Depending on how you want to to manage multiple rows being the max with the same subno, you might want to remove the last GROUP BY subno. With it, it only shows one of them. Without, it shows all the duplicated max rows.
We use row_number(), partition by SubNo and PO and order by Date Desc.
select Id
,Date
,SubNo
,PO
from
(
select *
,row_number() over(partition by SubNo, PO order by Date desc) as rn
from t
) t
where rn = 1
Id
Date
SubNo
PO
105
2022-11-04 12:43:00
1
800
103
2022-11-03 14:00:00
1
923
104
2022-11-03 15:00:00
2
800
Fiddle
Related
I have a dataset like this, where there can be multiple transactions per trade
| tx_id | trade_id |
--------------------
| 100 | 11 |
| 99 | 11 |
| 98 | 11 |
| 97 | 10 |
| 96 | 10 |
| 95 | 9 |
| 94 | 9 |
| 93 | 8 |
...
I want to select all of the transactions from the last N trades. For instance if I wanted to select all rows from the last 2 trades, I would get:
| tx_id | trade_id |
--------------------
| 100 | 11 |
| 99 | 11 |
| 98 | 11 |
| 97 | 10 |
| 96 | 10 |
I cannot guarantee that the trade_id will always have an interval of 1.
How can I accomplish this in mysql?
This will also work with mysql 5
Changing the linit , you can choose how many trades you want to receive
CREATE TABLE tab1 (
`tx_id` INTEGER,
`trade_id` INTEGER
);
INSERT INTO tab1
(`tx_id`, `trade_id`)
VALUES
('100', '11'),
('99', '11'),
('98', '11'),
('97', '10'),
('96', '10'),
('95', '9'),
('94', '9'),
('93', '8');
SELECT t1.* FROM tab1 t1 JOIN (SELECT DISTINCT `trade_id` FROM tab1 ORDER BY `trade_id` DESC LIMIT 2) t2
ON t1.`trade_id` = t2.`trade_id`
tx_id | trade_id
----: | -------:
100 | 11
99 | 11
98 | 11
97 | 10
96 | 10
db<>fiddle here
You use DENSE_RANK on trade_id descending, then filter on your required X for "last X":
CREATE TABLE t (tx_id int, trade_id int);
INSERT INTO t (tx_id, trade_id) VALUES
(100,11),
(99,11),
(98,11),
(97,10),
(96,10),
(95,9),
(94,9),
(93,8);
SET #ngroups=2;
WITH dat
AS
(
SELECT tx_id, trade_id, DENSE_RANK() OVER (ORDER BY trade_id DESC) AS trade_id_rank
FROM t
)
SELECT tx_id, trade_id
FROM dat
WHERE trade_id_rank <= #ngroups;
dbfiddle.uk
If we assume the "last trades" are the ones with the highest trade_id numbers, then you can use DENSE_RANK().
For example:
select *
from (
select *,
dense_rank() over(order by trade_id desc) as dr
from t
) x
where dr <= 2
This can be done with a CTE
WITH trades AS
SELECT trade_id tid
FROM myTable
GROUP BY trade_id
ORDER BY trade_id
LIMIT 2
SELECT * FROM
trades
JOIN myTable ON trade_id = tid
ORDER BY tx_id;
I have a user_accounts table with 6 columns:
id, user_id, amount, type, total_balance, created_at
1 101 10 debit 90 2018-09-14 20:10:49
2 101 30 credit 120 2018-09-14 20:10:52
3 102 210 credit 310 2018-09-14 21:10:52
4 102 10 debit 300 2018-09-14 21:10:54
5 103 10 credit 110 2018-09-14 21:10:54
6 104 15 credit 115 2018-09-14 21:11:59
I want to keep latest n rows of each user's and delete the rest of rows.
What is the best way to construct this query in mysql?
You can try to make row number by each userId and order by created_at in a subquery.
then delete ID on each userId by the rn
From my sample, I only keep the first least row so I set rn > 1
CREATE TABLE T(
id int,
user_id int,
amount int,
type varchar(50),
total_balance int,
created_at datetime
);
insert into T values (1,101,10 ,'debit',90 ,'2018-09-14 20:10:49');
insert into T values (2,101,30 ,'credit',120,'2018-09-14 20:10:52');
insert into T values (7,101,30 ,'credit',120,'2018-09-16 20:10:52');
insert into T values (3,102,210,'credit',310,'2018-09-14 21:10:52');
insert into T values (4,102,10 ,'debit',300,'2018-09-14 21:10:54');
insert into T values (5,103,10 ,'credit',110,'2018-09-14 21:10:54');
insert into T values (6,104,15 ,'credit',115,'2018-09-14 21:11:59');
DELETE FROM T
WHERE ID IN (
SELECT ID
FROM
(
SELECT ID,(
SELECT COUNT(*)
FROM T tt
WHERE
tt.user_id = t1.user_id
AND
tt.created_at >= t1.created_at
ORDER BY
tt.created_at desc
) rn
FROM T t1
) deltable
where rn > 1 # n least rows you want to keep.
);
Query 1:
SELECT * FROM T
Results:
| id | user_id | amount | type | total_balance | created_at |
|----|---------|--------|--------|---------------|----------------------|
| 7 | 101 | 30 | credit | 120 | 2018-09-16T20:10:52Z |
| 4 | 102 | 10 | debit | 300 | 2018-09-14T21:10:54Z |
| 5 | 103 | 10 | credit | 110 | 2018-09-14T21:10:54Z |
| 6 | 104 | 15 | credit | 115 | 2018-09-14T21:11:59Z |
You can try with following query. Here N is number of rows you want to keep
DELETE FROM user_accounts WHERE id NOT IN (select id FROM user_accounts ORDER BY created_at DESC LIMIT N)
I have a table that can be simplified as:
ID |team_id | submission file | date
========================================
1 | 1756 | final_project.c |2018-06-22 19:00:00
2 | 1923 | asdf.c |2018-06-22 16:00:00
3 | 1756 | untitled.c |2018-06-21 20:00:00
4 | 1923 | my_project.c |2018-06-21 14:00:00
5 | 1756 | untitled.c |2018-06-21 08:00:00
6 | 1814 | my_project.c |2018-06-20 12:00:00
This is a table of people submitting their projects to me, but I only want each individual students' most recent submission, with each student having a unique team_id.
How do I recall the most recent row of each team_id so that my recall looks like this:
ID |team_id | submission file | date
========================================
1 | 1756 | final_project.c |2018-06-22 19:00:00
2 | 1923 | asdf.c |2018-06-22 16:00:00
6 | 1814 | my_project.c |2018-06-20 12:00:00
Thank you for the help!
Subquery will do what you want with correlation approach :
select t.*
from table t -- Need to replace table with your table-name i.e. Projecttble, etc..
where id = (select t1.id
from table t1 -- Need to replace table with your table-name
where t1.team_id = t.team_id
order by t1.date desc
limit 1
);
You could use a self join to pick most recent row per team
select a.*
from your_table a
join (
select team_id, max(date) date
from your_table
group by team_id
) b on a.team_id = b.team_id and a.date = b.date
EDIT: Yogesh beat me to the MySQL 5 answer while I was AFK. You'll want to join your subquery on both the team_id and the submission_file in case you get multiple file submissions from a team on the same day.
Depending on what version of MySQL you are using, this can be done different ways.
SETUP
CREATE TABLE t1 (ID int, team_id int, submission_file varchar(30), the_date date) ;
INSERT INTO t1 (ID,team_id,submission_file,the_date)
SELECT 1, 1756, 'final_project.c', '2018-06-20 19:00:00' UNION ALL
SELECT 2, 1923, 'asdf.c', '2018-06-22 16:00:00' UNION ALL /**/
SELECT 3, 1756, 'untitled.c', '2018-06-21 20:00:00' UNION ALL /**/
SELECT 4, 1923, 'my_project.c', '2018-06-21 14:00:00' UNION ALL /**/
SELECT 5, 1756, 'untitled.c', '2018-06-21 08:00:00' UNION ALL
SELECT 6, 1814, 'my_project.c', '2018-06-20 12:00:00' UNION ALL/**/
SELECT 7, 1756, 'final_project.c', '2018-06-21 19:00:00' UNION ALL
SELECT 8, 1756, 'final_project.c', '2018-06-22 00:00:00' /**/
;
QUERIES
If you are using MySQL 5.x or lower, then you'll want to use a correlated subquery with a LIMIT on it to pull up just the rows you want.
/* MySQL <8 */
SELECT a.*
FROM t1 a
WHERE a.id = (
SELECT b.id
FROM t1 b
WHERE b.team_id = a.team_id
AND b.submission_file = a.submission_file
ORDER BY b.the_date DESC
LIMIT 1
) ;
ID | team_id | submission_file | the_date
-: | ------: | :-------------- | :---------
2 | 1923 | asdf.c | 2018-06-22
3 | 1756 | untitled.c | 2018-06-21
4 | 1923 | my_project.c | 2018-06-21
6 | 1814 | my_project.c | 2018-06-20
8 | 1756 | final_project.c | 2018-06-22
MySQL 8 added window functions (FINALLY), and this makes a problem like this MUCH easier to solve, and likely much more efficient, too. You can sort the rows you need with a ROW_NUMBER() window function.
/* MySQL 8+ */
SELECT s1.ID, s1.team_id, s1.submission_file, s1.the_date
FROM (
SELECT ID, team_id, submission_file, the_date
, ROW_NUMBER() OVER (PARTITION BY team_id, submission_file ORDER BY the_date DESC) AS rn
FROM t1
) s1
WHERE rn = 1
;
ID | team_id | submission_file | the_date
-: | ------: | :-------------- | :---------
8 | 1756 | final_project.c | 2018-06-22
3 | 1756 | untitled.c | 2018-06-21
6 | 1814 | my_project.c | 2018-06-20
2 | 1923 | asdf.c | 2018-06-22
4 | 1923 | my_project.c | 2018-06-21
db<>fiddle here
NOTE: After re-reading the OP, the intent may be different than what I originally read. In my queries, my filtering will return the most recent of all unique submission_file names that a team submitted. So if a team submitted 3 files, you will get all 3 of the most recent versions of those files. If you remove submission_file from the 5 subquery and the 8 PARTITION BY, it will return only the most recent single file a team submitted regardless of name.
I have such table in my MySQL database:
---------------------------
|fid | price | date |
---------------------------
| 1 | 1.23 | 2011-08-11 |
| 1 | 1.43 | 2011-08-12 |
| 1 | 1.54 | 2011-08-13 |
| 1 | 1.29 | 2011-08-14 |
| 1 | 1.60 | 2011-08-15 |
| 1 | 1.80 | 2011-08-16 |
fid - this is the product id
price - this is the price of the product in specified day
I want to calculate average price of the product fid=1. I want to calculate the average price of first n=3 rows ordered by date for specified fid, and then calculate average price for another 3 rows ordered by date.
How can I group first 3 rows and calculate avg and then group next 3 rows and calculate avg. Before calculation I need to sort the rows by date and then group n rows.
If n=3 this should return such result:
--------------
|fid | price |
--------------
| 1 | 1.40 | 2011-08-11 -> 2011-08-13 - average price for 3 days
| 1 | 1.56 | 2011-08-14 -> 2011-08-16 - average price for 3 days
How can I create SQL Query to do such calculations?
Thanks in advance.
Unluckily mysql doesn't offer analytic functions like oracle,mssql and postgres do. So you have to play with variables to reach your goal.
create table mytest (
id int not null auto_increment primary key,
fid int,
price decimal(4,2),
fdate date
) engine = myisam;
insert into mytest (fid,price,fdate)
values
(1,1.23,'2011-08-11'),
(1,1.43,'2011-08-12'),
(1,1.54,'2011-08-13'),
(1,1.29,'2011-08-14'),
(1,1.60,'2011-08-15'),
(1,1.80,'2011-08-16');
select
concat_ws('/',min(fdate),max(fdate)) as rng,
format(avg(price),2) as average from (
select *,#riga:=#riga+1 as riga
from mytest,(select #riga:=0) as r order by fdate
) as t
group by ceil(riga/3);
+-----------------------+---------+
| rng | average |
+-----------------------+---------+
| 2011-08-11/2011-08-13 | 1.40 |
| 2011-08-14/2011-08-16 | 1.56 |
+-----------------------+---------+
2 rows in set (0.02 sec)
maybe you could use
GROUP BY FLOOR(UNIX_TIMESTAMP(date)/(60*60*24*3))
= convert to secounds, divide by secounds for 3 days, and round down
SELECT AVG( price ) FROM my_table
GROUP BY ( date - ( SELECT MIN( date ) FROM my_table WHERE fid = 1 ) ) DIV 3
WHERE fid = 1
select fid, avg(price), min(date), max(date)
from
(select floor((#rownum := #rownum + 1)/3) as `rank`, prices.*
from prices, (SELECT #rownum:=-1) as r
order by date) as t
group by rank
My goal is to return a start and end date having same value in a column. Here is my table. The (*) have been marked to give you the idea of how I want to get "EndDate" for every similar sequence value of A & B columns
ID | DayDate | A | B
-----------------------------------------------
1 | 2010/07/1 | 200 | 300
2 | 2010/07/2 | 200 | 300 *
3 | 2010/07/3 | 150 | 250
4 | 2010/07/4 | 150 | 250 *
8 | 2010/07/5 | 150 | 350 *
9 | 2010/07/6 | 200 | 300
10 | 2010/07/7 | 200 | 300 *
11 | 2010/07/8 | 100 | 200
12 | 2010/07/9 | 100 | 200 *
and I want to get the following result table from the above table
| DayDate |EndDate | A | B
-----------------------------------------------
| 2010/07/1 |2010/07/2 | 200 | 300
| 2010/07/3 |2010/07/4 | 150 | 250
| 2010/07/5 |2010/07/5 | 150 | 350
| 2010/07/6 |2010/07/7 | 200 | 300
| 2010/07/8 |2010/07/9 | 100 | 200
UPDATE:
Thanks Mike, The approach of yours seems to work in your perspective of considering the following row as a mistake.
8 | 2010/07/5 | 150 | 350 *
However it is not a mistake. The challenge I am faced with this type of data is like a scenario of logging a market price change with date. The real problem in mycase is to select all rows with the beginning and ending date if both A & B matches in all these rows. Also to select the rows which are next to previously selected, and so on like that no data is left out in the table.
I can explain a real world scenario. A Hotel with Room A and B has room rates for each day entered in to table as explained in my question. Now the hotel needs to get a report to show the price calendar in a shorter way using start and end date, instead of listing all the dates entered. For example, on 2010/07/01 to 2010/07/02 the price of A is 200 and B is 300. This price is changed from 3rd to 4th and on 5th there is a different price only for that day where the Room B is price is changed to 350. So this is considered as a single day difference, thats why start and end dates are same.
I hope this explained the scenario of the problem. Also note that this hotel may be closed for a specific time period, lets say this is an additional problem to my first question. The problem is what if the rate is not entered on specific dates, for example on Sundays the hotel do not sell these two rooms so they entered no price, meaning the row will not exist in the table.
Creating related tables allows you much greater freedom to query and extract relevant information. Here's a few links that you might find useful:
You could start with these tutorials:
http://dev.mysql.com/tech-resources/articles/intro-to-normalization.html
http://net.tutsplus.com/tutorials/databases/sql-for-beginners/
There are also a couple of questions here on stackoverflow that might be useful:
Normalization in plain English
What exactly does database normalization do?
Anyway, on to a possible solution. The following examples use your hotel rooms analogy.
First, create a table to hold information about the hotel rooms. This table just contains the room ID and its name, but you could store other information in here, such as the room type (single, double, twin), its view (ocean front, ocean view, city view, pool view), and so on:
CREATE TABLE `room` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`name` VARCHAR(45) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE INDEX `name_UNIQUE` (`name` ASC) )
ENGINE = InnoDB;
Now create a table to hold the changing room rates. This table links to the room table through the room_id column. The foreign key constraint prevents records being inserted into the rate table which refer to rooms that do not exist:
CREATE TABLE `rate` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
`room_id` INT UNSIGNED NOT NULL,
`date` DATE NOT NULL,
`rate` DECIMAL(6,2) UNSIGNED NOT NULL,
PRIMARY KEY (`id`),
INDEX `fk_room_rate` (`room_id` ASC),
CONSTRAINT `fk_room_rate`
FOREIGN KEY (`room_id` )
REFERENCES `room` (`id` )
ON DELETE CASCADE
ON UPDATE CASCADE)
ENGINE = InnoDB;
Create two rooms, and add some daily rate information about each room:
INSERT INTO `room` (`id`, `name`) VALUES (1, 'A'), (2, 'B');
INSERT INTO `rate` (`id`, `room_id`, `date`, `rate`) VALUES
( 1, 1, '2010-07-01', 200),
( 2, 1, '2010-07-02', 200),
( 3, 1, '2010-07-03', 150),
( 4, 1, '2010-07-04', 150),
( 5, 1, '2010-07-05', 150),
( 6, 1, '2010-07-06', 200),
( 7, 1, '2010-07-07', 200),
( 8, 1, '2010-07-08', 100),
( 9, 1, '2010-07-09', 100),
(10, 2, '2010-07-01', 300),
(11, 2, '2010-07-02', 300),
(12, 2, '2010-07-03', 250),
(13, 2, '2010-07-04', 250),
(14, 2, '2010-07-05', 350),
(15, 2, '2010-07-06', 300),
(16, 2, '2010-07-07', 300),
(17, 2, '2010-07-08', 200),
(18, 2, '2010-07-09', 200);
With that information stored, a simple SELECT query with a JOIN will show you the all the daily room rates:
SELECT
room.name,
rate.date,
rate.rate
FROM room
JOIN rate
ON rate.room_id = room.id;
+------+------------+--------+
| A | 2010-07-01 | 200.00 |
| A | 2010-07-02 | 200.00 |
| A | 2010-07-03 | 150.00 |
| A | 2010-07-04 | 150.00 |
| A | 2010-07-05 | 150.00 |
| A | 2010-07-06 | 200.00 |
| A | 2010-07-07 | 200.00 |
| A | 2010-07-08 | 100.00 |
| A | 2010-07-09 | 100.00 |
| B | 2010-07-01 | 300.00 |
| B | 2010-07-02 | 300.00 |
| B | 2010-07-03 | 250.00 |
| B | 2010-07-04 | 250.00 |
| B | 2010-07-05 | 350.00 |
| B | 2010-07-06 | 300.00 |
| B | 2010-07-07 | 300.00 |
| B | 2010-07-08 | 200.00 |
| B | 2010-07-09 | 200.00 |
+------+------------+--------+
To find the start and end dates for each room rate, you need a more complex query:
SELECT
id,
room_id,
MIN(date) AS start_date,
MAX(date) AS end_date,
COUNT(*) AS days,
rate
FROM (
SELECT
id,
room_id,
date,
rate,
(
SELECT COUNT(*)
FROM rate AS b
WHERE b.rate <> a.rate
AND b.date <= a.date
AND b.room_id = a.room_id
) AS grouping
FROM rate AS a
ORDER BY a.room_id, a.date
) c
GROUP BY rate, grouping
ORDER BY room_id, MIN(date);
+----+---------+------------+------------+------+--------+
| id | room_id | start_date | end_date | days | rate |
+----+---------+------------+------------+------+--------+
| 1 | 1 | 2010-07-01 | 2010-07-02 | 2 | 200.00 |
| 3 | 1 | 2010-07-03 | 2010-07-05 | 3 | 150.00 |
| 6 | 1 | 2010-07-06 | 2010-07-07 | 2 | 200.00 |
| 8 | 1 | 2010-07-08 | 2010-07-09 | 2 | 100.00 |
| 10 | 2 | 2010-07-01 | 2010-07-02 | 2 | 300.00 |
| 12 | 2 | 2010-07-03 | 2010-07-04 | 2 | 250.00 |
| 14 | 2 | 2010-07-05 | 2010-07-05 | 1 | 350.00 |
| 15 | 2 | 2010-07-06 | 2010-07-07 | 2 | 300.00 |
| 17 | 2 | 2010-07-08 | 2010-07-09 | 2 | 200.00 |
+----+---------+------------+------------+------+--------+
You can find a good explanation of the technique used in the above query here:
http://www.sqlteam.com/article/detecting-runs-or-streaks-in-your-data
My general approach is to join the table onto itself based on DayDate = DayDate+1 and the A or B values not being equal
This will find the end dates for each period (where the value is going to be different on the following day)
The only problem is, that won't find an end date for the final period. To get around this, I selct the max date from the table and union that into my list of end dates
Once you have the list of end dates defined, you can join them to the original table based on the end date being greater than or equal to the original date
From this final list, select the minimum daydate grouped by the other fields
select
min(DayDate) as DayDate,EndDate,A,B from
(SELECT DayDate, A, B, min(ends.EndDate) as EndDate
FROM yourtable
LEFT JOIN
(SELECT max(DayDate) as EndDate FROM yourtable UNION
SELECT t1.DayDate as EndDate
FROM yourtable t1
JOIN yourtable t2
ON date_add(t1.DayDate, INTERVAL 1 DAY) = t2.DayDate
AND (t1.A<>t2.A OR t1.B<>t2.B)) ends
ON ends.EndDate>=DayDate
GROUP BY DayDate, A, B) x
GROUP BY EndDate,A,B
I think I have found a solution which does produce the table desired.
SELECT
a.DayDate AS StartDate,
( SELECT b.DayDate
FROM Dates AS b
WHERE b.DayDate > a.DayDate AND (b.B = a.B OR b.B IS NULL)
ORDER BY b.DayDate ASC LIMIT 1
) AS StopDate,
a.A as A,
a.B AS B
FROM Dates AS a
WHERE Coalesce(
(SELECT c.B
FROM Dates AS c
WHERE c.DayDate <= a.DayDate
ORDER BY c.DayDate DESC LIMIT 1,1
), -99999
) <> a.B
AND a.B IS NOT NULL
ORDER BY a.DayDate ASC;
is able to generate the following table result
StartDate StopDate A B
2010-07-01 2010-07-02 200 300
2010-07-03 2010-07-04 150 250
2010-07-05 NULL 150 350
2010-07-06 2010-07-07 200 300
2010-07-08 2010-07-09 100 200
But I need a way to replace the NULL with the same date of the start date.