Sqlserver
 sql >> Teknologi Basis Data >  >> RDS >> Sqlserver

Dapatkan catatan bulan lalu di SQL server

Semua jawaban yang ada (berfungsi) memiliki satu dari dua masalah:

  1. Mereka akan mengabaikan indeks pada kolom yang dicari
  2. Keinginan (berpotensi) memilih data yang tidak dimaksudkan, secara diam-diam merusak hasil Anda.

1. Indeks yang Diabaikan:

Untuk sebagian besar, ketika kolom yang dicari memiliki fungsi yang dipanggil (termasuk secara implisit, seperti untuk CAST ), pengoptimal harus mengabaikan indeks pada kolom dan menelusuri setiap catatan. Berikut ini contoh singkatnya:

Kita berurusan dengan stempel waktu, dan sebagian besar RDBMS cenderung menyimpan informasi ini sebagai semacam peningkatan nilai, biasanya long atau BIGINTEGER hitungan mili-/nanodetik. Waktu saat ini terlihat/disimpan seperti ini:

1402401635000000  -- 2014-06-10 12:00:35.000000 GMT

Anda tidak melihat nilai 'Tahun' ('2014' ) di sana, kan? Faktanya, ada sedikit matematika yang rumit untuk diterjemahkan bolak-balik. Jadi, jika Anda memanggil salah satu fungsi bagian ekstraksi/tanggal pada kolom yang dicari, server harus melakukan semua matematika itu hanya untuk mencari tahu apakah Anda dapat memasukkannya ke dalam hasil. Pada tabel kecil ini bukan masalah, tetapi karena persentase baris yang dipilih berkurang, ini menjadi saluran yang lebih besar dan lebih besar. Kemudian dalam hal ini, Anda melakukannya untuk kedua kalinya untuk menanyakan tentang MONTH ... yah, Anda mendapatkan gambarannya.

2. Data yang tidak diinginkan:

Bergantung pada versi SQL Server tertentu, dan tipe data kolom, menggunakan BETWEEN (atau rentang batas atas inklusif serupa:<= ) dapat mengakibatkan pemilihan data yang salah. Pada dasarnya, Anda berpotensi memasukkan data dari tengah malam hari "berikutnya", atau mengecualikan beberapa bagian dari catatan hari "saat ini".

Apa yang seharusnya lakukan:

Jadi kami membutuhkan cara yang aman untuk data kami, dan akan menggunakan indeks (jika memungkinkan). Cara yang benar adalah dalam bentuk:

WHERE date_created >= @startOfPreviousMonth AND date_created < @startOfCurrentMonth

Mengingat hanya ada satu bulan, @startOfPreviousMonth dapat dengan mudah diganti/diturunkan dengan:

DATEADD(month, -1, @startOCurrentfMonth)

Jika Anda perlu mendapatkan awal bulan saat ini di server, Anda dapat melakukannya melalui yang berikut:

DATEADD(month, DATEDIFF(month, 0, CURRENT_TIMESTAMP), 0)

Penjelasan singkat di sini. DATEDIFF(...) awal akan mendapatkan perbedaan antara awal era saat ini (0001-01-01 - AD, CE, apa pun), pada dasarnya mengembalikan bilangan bulat besar. Ini adalah hitungan bulan ke awal saat ini bulan. Kami kemudian menambahkan nomor ini ke awal era, yaitu pada awal bulan tertentu.

Jadi skrip lengkap Anda bisa/harus terlihat seperti berikut:

DECLARE @startOfCurrentMonth DATETIME
SET @startOfCurrentMonth = DATEADD(month, DATEDIFF(month, 0, CURRENT_TIMESTAMP), 0)

SELECT *
FROM Member
WHERE date_created >= DATEADD(month, -1, @startOfCurrentMonth) -- this was originally    misspelled
      AND date_created < @startOfCurrentMonth

Dengan demikian, semua operasi tanggal hanya dilakukan sekali, pada satu nilai; pengoptimal bebas menggunakan indeks, dan tidak ada data yang salah yang akan disertakan.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. DATEDIFF() Mengembalikan Hasil yang Salah di SQL Server? Baca ini.

  2. Kembalikan Nama Login Saat Ini di SQL Server (T-SQL)

  3. 4 Tips untuk Menyiapkan Peringatan SQL Server Anda

  4. pyodbc.connect() berfungsi, tetapi tidak sqlalchemy.create_engine().connect()

  5. Mengapa pembacaan logis untuk fungsi agregat berjendela begitu tinggi?