2016-03-21 17 views
4

Bir tablo aşağıdaki yapıya benzeyen vardır:Sorgu sadece

City  start_date    end_date 
Paris  1995-01-01 00:00:00 1997-10-01 23:59:59 
Paris  1997-10-02 00:00:00 0001-01-01 00:00:00 
Paris  2013-01-25 00:00:00 0001-01-01 00:00:00 
Paris  2015-04-25 00:00:00 0001-01-01 00:00:00 
Berlin  2014-11-01 00:00:00 0001-01-01 00:00:00 
Berlin  2014-06-01 00:00:00 0001-01-01 00:00:00 
Berlin  2015-09-11 00:00:00 0001-01-01 00:00:00 
Berlin  2015-10-01 00:00:00 0001-01-01 00:00:00 
Milan  2001-01-01 00:00:00 0001-01-01 00:00:00 
Milan  2005-10-02 00:00:00 2006-10-02 23:59:59 
Milan  2006-10-03 00:00:00 2015-04-24 23:59:59 
Milan  2015-04-25 00:00:00 0001-01-01 00:00:00 

veri şehirlerde dayalı başlangıç ​​ve bitiş tarihleri ​​tarihsel bir görünüm içeriyor. Bir şehir için en yeni kayıt, en yüksek başlangıç ​​tarihine sahip olan ve '0001-01-01 00:00:00' bitiş tarihi olan ve bitiş tarihi olmadığını gösteren bir tarih olmalıdır.

ben bu verileri temizlemek ve tüm her şehir için tarihsel kayıtlar sonu sadece end_date 0001-01-01 00' ayarlandığında durumlarda, bir sonraki kaydın başlangıç ​​tarihinden önce bir saniye büyük olduğundan emin olmalısınız : 00: 00' . Bu nedenle, bitiş_tarihi gerçek bir tarihin olduğu durumlarda, bu göz ardı edilecektir. Ayrıca, bir şehir için en yeni başlangıç_tarihine sahip kaydın, bitiş_tarihi değiştirilmiş olması gerekmez.

çıkan tablo bu gibi görünmelidir:

City  start_date    end_date 
Paris  1995-01-01 00:00:00 1997-10-01 23:59:59 
Paris  1997-10-02 00:00:00 2013-01-24 23:59:59 
Paris  2013-01-25 00:00:00 2015-04-24 23:59:59 
Paris  2015-04-25 00:00:00 0001-01-01 00:00:00 
Berlin  2014-11-01 00:00:00 2014-05-31 23:59:59 
Berlin  2014-06-01 00:00:00 2015-09-10 23:59:59 
Berlin  2015-09-11 00:00:00 2015-09-30 23:59:59 
Berlin  2015-10-01 00:00:00 0001-01-01 23:59:59 
Milan  2001-01-01 00:00:00 2005-10-01 23:59:59 
Milan  2005-10-02 00:00:00 2006-10-02 23:59:59 
Milan  2006-10-03 00:00:00 2015-04-24 23:59:59 
Milan  2015-04-25 00:00:00 0001-01-01 00:00:00 

Ben this question bir kullanıcı tarafından önerilen şu senaryoyu çalıştık.

update test join 
     (select t.*, 
       (select min(start_date) 
       from test t2 
       where t2.city = t.city and 
         t2.start_date > t.start_date 
       order by t2.start_date 
       limit 1 
       ) as next_start_date 
     from test t 
     ) tt 
     on tt.city = test.city and tt.start_date = test.start_date 
    set test.end_date = date_sub(tt.next_start_date, interval 1 second) 
where test.end_date = '0001-01-01' and 
     next_start_date is not null; 

Ne yazık ki istendiği gibi, bazı end_dates değildir (örneğin kimlik numarası 5 için ve 6), Berlin kayıtları itibaren. Ancak diğerleri, olması gerektiği gibi görünmektedir. Bu aşağıda gösterilmiştir: Burada

enter image description here

oluşturmak ve eklemek ifadeleri çoğaltmak mümkün şunlardır:

CREATE TABLE `test` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `city` varchar(50) DEFAULT NULL, 
    `start_date` datetime DEFAULT NULL, 
    `end_date` datetime DEFAULT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8; 

INSERT INTO test (city, start_date, end_date) VALUES ('Paris','1995-01-01 00:00:00','1997-10-01 23:59:59'); 
INSERT INTO test (city, start_date, end_date) VALUES ('Paris','1997-10-02 00:00:00','0001-01-01 00:00:00'); 
INSERT INTO test (city, start_date, end_date) VALUES ('Paris','2013-01-25 00:00:00','0001-01-01 00:00:00'); 
INSERT INTO test (city, start_date, end_date) VALUES ('Paris','2015-04-25 00:00:00','0001-01-01 00:00:00'); 
INSERT INTO test (city, start_date, end_date) VALUES ('Berlin','2014-11-01 00:00:00','0001-01-01 00:00:00'); 
INSERT INTO test (city, start_date, end_date) VALUES ('Berlin','2014-06-01 00:00:00','0001-01-01 00:00:00'); 
INSERT INTO test (city, start_date, end_date) VALUES ('Berlin','2015-09-11 00:00:00','0001-01-01 00:00:00'); 
INSERT INTO test (city, start_date, end_date) VALUES ('Berlin','2015-10-01 00:00:00','0001-01-01 00:00:00'); 
INSERT INTO test (city, start_date, end_date) VALUES ('Milan','2001-01-01 00:00:00','0001-01-01 00:00:00'); 
INSERT INTO test (city, start_date, end_date) VALUES ('Milan','2005-10-02 00:00:00','2006-10-02 23:59:59'); 
INSERT INTO test (city, start_date, end_date) VALUES ('Milan','2006-10-03 00:00:00','2015-04-24 23:59:59'); 
INSERT INTO test (city, start_date, end_date) VALUES ('Milan','2015-04-25 00:00:00','0001-01-01 00:00:00'); 
+0

Kişisel 'UPDATE' deyimi verilen örnek verilerle Tamam çalıştı. Lütfen [this] (http://sqlfiddle.com/#!9/d879f/2) demosunu kontrol edin. –

cevap

-1
-- query wanted 
UPDATE test t1 INNER JOIN 
    (SELECT *, @id := @id + 1 AS new_id 
    FROM test CROSS JOIN (SELECT @id := 0) param 
    ORDER BY city, start_date) t2 
    ON t1.city = t2.city AND t1.start_date = t2.start_date 
    INNER JOIN 
    (SELECT *, @id2 := @id2 + 1 AS new_id 
    FROM test CROSS JOIN (SELECT @id2 := 0) param 
    ORDER BY city, start_date) t3 
    ON t2.new_id + 1 = t3.new_id AND t2.city = t3.city 
SET t1.end_date = DATE_SUB(t3.start_date, INTERVAL 1 SECOND) 
WHERE t1.end_date = '0001-01-01 00:00:00'; 

aşağıdaki tam demo.

SQL:

Çıktı
-- data 
CREATE TABLE `test` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `city` varchar(50) DEFAULT NULL, 
    `start_date` datetime DEFAULT NULL, 
    `end_date` datetime DEFAULT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8; 

INSERT INTO test (city, start_date, end_date) VALUES ('Paris','1995-01-01 00:00:00','1997-10-01 23:59:59'); 
INSERT INTO test (city, start_date, end_date) VALUES ('Paris','1997-10-02 00:00:00','0001-01-01 00:00:00'); 
INSERT INTO test (city, start_date, end_date) VALUES ('Paris','2013-01-25 00:00:00','0001-01-01 00:00:00'); 
INSERT INTO test (city, start_date, end_date) VALUES ('Paris','2015-04-25 00:00:00','0001-01-01 00:00:00'); 
INSERT INTO test (city, start_date, end_date) VALUES ('Berlin','2014-11-01 00:00:00','0001-01-01 00:00:00'); 
INSERT INTO test (city, start_date, end_date) VALUES ('Berlin','2014-06-01 00:00:00','0001-01-01 00:00:00'); 
INSERT INTO test (city, start_date, end_date) VALUES ('Berlin','2015-09-11 00:00:00','0001-01-01 00:00:00'); 
INSERT INTO test (city, start_date, end_date) VALUES ('Berlin','2015-10-01 00:00:00','0001-01-01 00:00:00'); 
INSERT INTO test (city, start_date, end_date) VALUES ('Milan','2001-01-01 00:00:00','0001-01-01 00:00:00'); 
INSERT INTO test (city, start_date, end_date) VALUES ('Milan','2005-10-02 00:00:00','2006-10-02 23:59:59'); 
INSERT INTO test (city, start_date, end_date) VALUES ('Milan','2006-10-03 00:00:00','2015-04-24 23:59:59'); 
INSERT INTO test (city, start_date, end_date) VALUES ('Milan','2015-04-25 00:00:00','0001-01-01 00:00:00'); 
select * from test; 

-- query wanted 
UPDATE test t1 INNER JOIN 
    (SELECT *, @id := @id + 1 AS new_id 
    FROM test CROSS JOIN (SELECT @id := 0) param 
    ORDER BY city, start_date) t2 
    ON t1.city = t2.city AND t1.start_date = t2.start_date 
    INNER JOIN 
    (SELECT *, @id2 := @id2 + 1 AS new_id 
    FROM test CROSS JOIN (SELECT @id2 := 0) param 
    ORDER BY city, start_date) t3 
    ON t2.new_id + 1 = t3.new_id AND t2.city = t3.city 
SET t1.end_date = DATE_SUB(t3.start_date, INTERVAL 1 SECOND) 
WHERE t1.end_date = '0001-01-01 00:00:00'; 

select * from test; 

:

mysql> -- query wanted 
mysql> UPDATE test t1 INNER JOIN 
    -> (SELECT *, @id := @id + 1 AS new_id 
    -> FROM test CROSS JOIN (SELECT @id := 0) param 
    -> ORDER BY city, start_date) t2 
    -> ON t1.city = t2.city AND t1.start_date = t2.start_date 
    -> INNER JOIN 
    -> (SELECT *, @id2 := @id2 + 1 AS new_id 
    -> FROM test CROSS JOIN (SELECT @id2 := 0) param 
    -> ORDER BY city, start_date) t3 
    -> ON t2.new_id + 1 = t3.new_id AND t2.city = t3.city 
    -> SET t1.end_date = DATE_SUB(t3.start_date, INTERVAL 1 SECOND) 
    -> WHERE t1.end_date = '0001-01-01 00:00:00'; 
rom tesQuery OK, 6 rows affected (0.00 sec) 
Rows matched: 6 Changed: 6 Warnings: 0 

mysql> select * from test; 
+----+--------+---------------------+---------------------+ 
| id | city | start_date   | end_date   | 
+----+--------+---------------------+---------------------+ 
| 13 | Paris | 1995-01-01 00:00:00 | 1997-10-01 23:59:59 | 
| 14 | Paris | 1997-10-02 00:00:00 | 2013-01-24 23:59:59 | 
| 15 | Paris | 2013-01-25 00:00:00 | 2015-04-24 23:59:59 | 
| 16 | Paris | 2015-04-25 00:00:00 | 0001-01-01 00:00:00 | 
| 17 | Berlin | 2014-11-01 00:00:00 | 2014-05-31 23:59:59 | 
| 18 | Berlin | 2014-06-01 00:00:00 | 2015-09-10 23:59:59 | 
| 19 | Berlin | 2015-09-11 00:00:00 | 2015-09-30 23:59:59 | 
| 20 | Berlin | 2015-10-01 00:00:00 | 0001-01-01 00:00:00 | 
| 21 | Milan | 2001-01-01 00:00:00 | 2005-10-01 23:59:59 | 
| 22 | Milan | 2005-10-02 00:00:00 | 2006-10-02 23:59:59 | 
| 23 | Milan | 2006-10-03 00:00:00 | 2015-04-24 23:59:59 | 
| 24 | Milan | 2015-04-25 00:00:00 | 0001-01-01 00:00:00 | 
+----+--------+---------------------+---------------------+ 
12 rows in set (0.00 sec) 
+0

Bu sorgu, id değerinin her şehir için sıralı olacağını varsayar mı? 'Id + 1' katılım koşulunu fark ettiğimden. Öyleyse, her şehir için kayıtlar birbiri ardına tamamen eklenemeyeceğinden, maalesef her durumda işe yaramaz. –

+0

Her bir kayıt için parametrelerin manuel olarak doldurulması gerekiyor mu? –

+0

Yani @id değerlerinin doldurulması gerekmiyor mu? –