Mysql
 sql >> Teknologi Basis Data >  >> RDS >> Mysql

SQL - Temukan semua waktu henti dan lamanya waktu henti dari data MySQL (kumpulan baris dengan stempel waktu dan pesan status)

Inilah salah satu pendekatannya.

Mulailah dengan mengurutkan baris status berdasarkan stempel waktu (tampilan sebaris alias sebagai s ). Kemudian gunakan variabel pengguna MySQL untuk menyimpan nilai dari baris sebelumnya, saat Anda memproses setiap baris.

Apa yang sebenarnya kami cari adalah status 'naik' yang segera mengikuti urutan status 'turun'. Dan ketika kami menemukan baris dengan status 'naik', yang sebenarnya kami butuhkan adalah stempel waktu paling awal dari rangkaian status 'turun' sebelumnya.

Jadi, sesuatu seperti ini akan berhasil:

SELECT d.start_down
     , d.ended_down
  FROM (SELECT @i := @i + 1 AS i
             , @start := IF(s.status = 'down' AND (@status = 'up' OR @i = 1), s.time, @start) AS start_down
             , @ended := IF(s.status = 'up' AND @status = 'down', s.time, NULL) AS ended_down
             , @status := s.status
         FROM (SELECT t.time
                    , t.status
                 FROM mydata t
                WHERE t.status IN ('up','down')
                ORDER BY t.time ASC, t.status ASC
              ) s
         JOIN (SELECT @i := 0, @status := 'up', @ended := NULL, @start := NULL) i
      ) d
WHERE d.start_down IS NOT NULL
  AND d.ended_down IS NOT NULL

Ini berfungsi untuk kumpulan data tertentu yang Anda tampilkan.

Apa yang tidak ditangani (apa yang tidak dikembalikan) adalah periode 'turun' yang belum berakhir, yaitu urutan status 'turun' tanpa status 'naik'.

Untuk menghindari operasi pengurutan file untuk mengembalikan baris secara berurutan, Anda akan menginginkan indeks penutup pada (time,status) . Kueri ini akan menghasilkan tabel sementara (MyISAM) untuk mewujudkan tampilan inline alias sebagai d .

CATATAN: Untuk memahami apa yang dilakukan kueri ini, lepaskan kueri terluar itu, dan jalankan kueri hanya untuk tampilan sebaris alias sebagai d (Anda dapat menambahkan s.time ke daftar pilihan.)

Kueri ini mendapatkan setiap baris dengan status 'naik' atau 'turun'. "Trik"nya adalah menetapkan waktu "mulai" dan "akhir" (menandai periode turun) hanya pada baris yang mengakhiri periode 'turun'. (Artinya, baris pertama dengan status 'naik' mengikuti baris dengan status 'turun'.) Di sinilah pekerjaan sebenarnya dilakukan, kueri terluar hanya menyaring semua baris "ekstra" di hasil ini (yang kita tidak perlu.)

SELECT @i := @i + 1 AS i
     , @start := IF(s.status = 'down' AND (@status = 'up' OR @i = 1), s.time, @start) AS start_down
     , @ended := IF(s.status = 'up' AND @status = 'down', s.time, NULL) AS ended_down
     , @status := s.status
     , s.time
  FROM (SELECT t.time
             , t.status
          FROM mydata t
         WHERE t.status IN ('up','down')
         ORDER BY t.time ASC, t.status ASC
       ) s
  JOIN (SELECT @i := 0, @status := 'up', @ended := NULL, @start := NULL) i

Tujuan tampilan sebaris alias sebagai s adalah untuk mendapatkan baris yang diurutkan berdasarkan nilai stempel waktu, sehingga kami dapat memprosesnya secara berurutan. Tampilan inline alias sebagai i hanya ada di sana sehingga kami dapat menginisialisasi beberapa variabel pengguna di awal kueri.

Jika kami menjalankan Oracle atau SQL Server, kami dapat menggunakan "fungsi analitik" atau "fungsi peringkat" (sesuai namanya masing-masing.) MySQL tidak menyediakan hal seperti itu, jadi kami harus "menggulung sendiri ".



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. MYSQL &Phpmyadmin tidak menampilkan DB yang sama

  2. Ekstrak bidang tertentu dari file teks

  3. Seberapa amankah otentikasi dalam protokol mysql?

  4. Cara menyisipkan baris dalam tabel di antara dua baris yang ada di Sql

  5. Cara menggunakan GROUP BY setelah klausa Memiliki Mysql