Kami memiliki tabel perjanjian seperti yang ditunjukkan di bawah ini. Setiap janji temu harus dikategorikan sebagai "Baru" atau "Tindak Lanjut". Setiap janji temu (untuk seorang pasien) dalam waktu 30 hari sejak perjanjian pertama (dari pasien itu) adalah Tindak Lanjut. Setelah 30 hari, janji temu kembali "Baru". Setiap janji dalam 30 hari menjadi "Tindak Lanjut".
Saat ini saya melakukan ini dengan mengetikkan loop sementara.
Bagaimana mencapai ini tanpa WHILE loop?
Meja
CREATE TABLE #Appt1 (ApptID INT, PatientID INT, ApptDate DATE)
INSERT INTO #Appt1
SELECT 1,101,'2020-01-05' UNION
SELECT 2,505,'2020-01-06' UNION
SELECT 3,505,'2020-01-10' UNION
SELECT 4,505,'2020-01-20' UNION
SELECT 5,101,'2020-01-25' UNION
SELECT 6,101,'2020-02-12' UNION
SELECT 7,101,'2020-02-20' UNION
SELECT 8,101,'2020-03-30' UNION
SELECT 9,303,'2020-01-28' UNION
SELECT 10,303,'2020-02-02'
fast_forward
kursor di atas kursor mungkin akan menjadi pilihan terbaik Anda, kinerja bijaksana.Jawaban:
Anda perlu menggunakan permintaan rekursif.
Periode 30 hari dihitung mulai dari prev (dan tidak mungkin untuk melakukannya tanpa rekursi / pembaruan unik / loop). Itu sebabnya semua jawaban yang ada hanya menggunakan
ROW_NUMBER
gagal.db <> demo biola
Keluaran:
Bagaimana itu bekerja:
Kelas serupa:
SUM bersyarat pada Oracle - Capping fungsi windowed
Jendela sesi (Analisis Azure Stream)
Menjalankan Total hingga kondisi tertentu benar - Pembaruan unik
Tambahan
Jangan pernah menggunakan kode ini untuk produksi!
Itu bisa dilakukan dalam putaran "tunggal" (pembaruan unik):
Pertanyaan:
db <> fiddle Pembaruan unik
sumber
RANGE x PRECEDING
klausa dengan benar .Anda bisa melakukan ini dengan cyt rekursif. Anda harus memesan terlebih dahulu dengan apptDate dalam setiap pasien. Itu bisa dicapai dengan run-of-the-mill cte.
Kemudian, di bagian jangkar cyt rekursif Anda, pilih pemesanan pertama untuk setiap pasien, tandai status sebagai 'baru', dan juga tandai apptDate sebagai tanggal dari catatan 'baru' terbaru.
Dalam bagian rekursif dari cyt rekursif Anda, kenaikan janji temu berikutnya, hitung selisih hari antara janji temu saat ini dan tanggal janji temu 'baru' terbaru. Jika lebih dari 30 hari, tandai 'baru' dan setel ulang tanggal janji temu baru. Kalau tidak, tandai sebagai 'tindak lanjut' dan hanya meneruskan hari-hari yang ada sejak tanggal janji baru.
Akhirnya, dalam permintaan dasar, cukup pilih kolom yang Anda inginkan.
Saya harus menyebutkan bahwa saya awalnya menghapus jawaban ini karena jawaban Abhijeet Khandagale tampaknya memenuhi kebutuhan Anda dengan permintaan yang lebih sederhana (setelah sedikit mengolahnya). Tetapi dengan komentar Anda kepadanya tentang kebutuhan bisnis Anda dan data sampel tambahan Anda, saya membatalkan pesanan saya karena percaya ini memenuhi kebutuhan Anda.
sumber
Saya tidak yakin itu persis seperti yang Anda terapkan. Tetapi opsi lain, yang layak disebutkan selain menggunakan cte, adalah menggunakan tabel temp dan memperbarui dalam "putaran". Jadi kita akan memperbarui tabel temp sementara semua status tidak diatur dengan benar dan membangun hasil dengan cara yang berulang. Kita dapat mengontrol jumlah iterasi menggunakan hanya variabel lokal.
Jadi kami membagi setiap iterasi menjadi dua tahap.
Begitu
Memperbarui. Baca komentar yang diberikan oleh Lukasz. Jauh lebih pintar. Saya meninggalkan jawaban saya hanya sebagai ide.
sumber
Saya percaya ungkapan umum rekursif adalah cara yang bagus untuk mengoptimalkan kueri menghindari loop, tetapi dalam beberapa kasus dapat menyebabkan kinerja yang buruk dan harus dihindari jika mungkin.
Saya menggunakan kode di bawah ini untuk menyelesaikan masalah dan mengujinya akan lebih banyak nilai, tetapi mendorong Anda untuk mengujinya dengan data nyata Anda juga.
Idenya cukup sederhana - Saya ingin memisahkan catatan dalam kelompok (30 hari), di mana kelompok catatan terkecil adalah
new
, yang lain adalahfollow ups
. Periksa bagaimana pernyataan itu dibuat:Begitu:
* 1.0 / 30
ditambahkan+ 0.000001
; juga, kami menggunakan fungsi plafon untuk mendapatkansmallest integer greater than, or equal to, the specified numeric expression
Itu dia. Memiliki grup seperti itu, kami cukup gunakan
ROW_NUMBER
untuk menemukan tanggal mulai kami dan menjadikannya sebagainew
dan meninggalkan sisanya sebagaifollow ups
.sumber
Dengan hormat kepada semua orang dan di IMHO,
Tidak ada banyak peningkatan kinerja saat menggunakan
Recursive CTE
danWindow Partition function
semuanya.Appid
harusint identity(1,1)
, atau harus semakin meningkatclustered index
.Selain manfaat lainnya, ini juga memastikan bahwa semua deretan
APPDate
pasien yang berurutan harus lebih besar.Dengan cara ini Anda dapat dengan mudah bermain
APPID
dalam kueri yang akan lebih efisien daripada menempatkaninequality
operator seperti>, <di APPDate. Menempatkaninequality
operator seperti>, <dalam APPID akan membantu Pengoptimal Sql.Juga harus ada dua kolom tanggal dalam tabel seperti
Karena ini adalah kolom paling penting di tabel paling penting, jadi tidak banyak pemain, konversi.
Jadi
Non clustered index
bisa dibuat di AppdateTes skrip saya dengan data sampel lain dan biar tahu sampel data mana yang tidak berfungsi. Bahkan jika itu tidak berhasil maka saya yakin itu bisa diperbaiki dalam logika skrip saya sendiri.
sumber
Meskipun tidak secara jelas dibahas dalam pertanyaan, mudah untuk mengetahui bahwa tanggal penunjukan tidak dapat dengan mudah dikategorikan oleh kelompok 30 hari. Itu tidak masuk akal bisnis. Dan Anda tidak dapat menggunakan id appt juga. Anda dapat membuat janji baru hari ini untuk
2020-09-06
. Inilah cara saya mengatasi masalah ini. Pertama, dapatkan janji temu pertama, lalu hitung selisih tanggal antara setiap janji temu dan appt pertama. Jika 0, atur ke 'Baru'. Jika <= 30 'Tindak Lanjut'. Jika> 30, tetapkan sebagai 'Bimbang' dan lakukan pemeriksaan putaran berikutnya hingga tidak ada lagi 'Bimbang'. Dan untuk itu, Anda benar-benar membutuhkan loop sementara, tetapi tidak mengulangi setiap tanggal janji, melainkan hanya beberapa set data. Saya memeriksa rencana eksekusi. Meskipun hanya ada 10 baris, biaya kueri secara signifikan lebih rendah daripada yang menggunakan CTE rekursif, tetapi tidak serendah metode tambahan Lukasz Szozda.sumber
Saya harap ini akan membantu Anda.
sumber
Anda bisa menggunakan
Case
pernyataan .Pertanyaannya adalah, haruskah kategori ini ditetapkan berdasarkan penunjukan awal, atau yang sebelumnya? Yaitu, jika seorang Pasien telah memiliki tiga janji, haruskah kita membandingkan janji yang ketiga dengan yang pertama, atau yang kedua?
Masalah Anda nyatakan yang pertama, begitulah cara saya menjawab. Jika bukan itu masalahnya, Anda ingin menggunakannya
lag
.Juga, perlu diingat bahwa
DateDiff
tidak membuat pengecualian untuk akhir pekan. Jika ini hanya hari kerja, Anda harus membuat fungsi Scalar-Valued Anda sendiri.sumber
menggunakan fungsi Lag
Demo -> https://rextester.com/TNW43808
sumber
apptDate
sebagaiorder by
kolomlag
fungsi (yang sebenarnya harus Anda id bukan jaminan apa pun), itu masih bisa dengan mudah dipatahkan dengan memperkenalkan lebih banyak janji tindak lanjut. Lihat demo Rextester ini misalnya. Selamat mencoba, ...New
dan bukan aFollowUp
. Ini lebih dari 30 hari sejak penunjukan pertama pasien itu ... Anda harus menghitung 30 hari sejak setiapNew
janji dan kemudian menggunakanNew
lagi ...Milik saya benar. Penulis salah, lihat sudah berlalu
sumber