WHIP লুপ ছাড়াই জিজ্ঞাসা করুন


18

নীচে প্রদর্শিত হিসাবে আমাদের অ্যাপয়েন্টমেন্ট টেবিল আছে। প্রতিটি অ্যাপয়েন্টমেন্টকে "নতুন" বা "ফলোআপ" হিসাবে শ্রেণীবদ্ধ করা দরকার। প্রথম অ্যাপয়েন্টমেন্টের 30 দিনের মধ্যে (কোনও রোগীর জন্য) কোনও অ্যাপয়েন্টমেন্ট (সেই রোগীর) ফলোআপ হয়। 30 দিন পরে, অ্যাপয়েন্টমেন্ট আবার "নতুন"। 30 দিনের মধ্যে কোনও অ্যাপয়েন্টমেন্ট "ফলোআপ" হয়ে যায়।

আমি বর্তমানে লুপটি টাইপ করে এটি করছি।
WHIP লুপ ছাড়া এটি কীভাবে অর্জন করবেন?

এখানে চিত্র বর্ণনা লিখুন

টেবিল

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' 

আমি আপনার চিত্রটি দেখতে পাচ্ছি না, তবে আমি নিশ্চিত করতে চাই, যদি একে অপরের কাছ থেকে প্রতি 20 দিনের মধ্যে 3 টি অ্যাপয়েন্টমেন্ট থাকে তবে শেষটি এখনও ঠিক 'অনুসরণ করে' থাকে, যদিও এটি প্রথম থেকে 30 দিনের বেশি হলেও, এটি মাঝ থেকে এখনও 20 দিনেরও কম। এটা কি সত্য?
pwilcox

@pwilcox নং তৃতীয়টি ছবিতে প্রদর্শিত নতুন অ্যাপয়েন্টমেন্ট হবে
LCJ

fast_forwardকার্সার লুপ ওভার সম্ভবত আপনার সেরা বিকল্প হতে পারে, কর্মক্ষমতা অনুযায়ী।
ডেভিড דודו মার্কোভিটস

উত্তর:


14

আপনার পুনরাবৃত্তি ক্যোয়ারী ব্যবহার করতে হবে।

30 দিনের সময়কাল পূর্ব থেকে শুরু করা গণনা করা হয় (এবং এটি পুনরাবৃত্তি / উদ্দীপনা আপডেট / লুপ ছাড়া এটি করা সম্ভব নয়)। এজন্য কেবল বিদ্যমান সমস্ত উত্তর উত্তর ROW_NUMBERব্যর্থ হয়েছে।

WITH f AS (
  SELECT *, rn = ROW_NUMBER() OVER(PARTITION BY PatientId ORDER BY ApptDate) 
  FROM Appt1
), rec AS (
  SELECT Category = CAST('New' AS NVARCHAR(20)), ApptId, PatientId, ApptDate, rn, startDate = ApptDate
  FROM f
  WHERE rn = 1
  UNION ALL
  SELECT CAST(CASE WHEN DATEDIFF(DAY,  rec.startDate,f.ApptDate) <= 30 THEN N'FollowUp' ELSE N'New' END AS NVARCHAR(20)), 
         f.ApptId,f.PatientId,f.ApptDate, f.rn,
         CASE WHEN DATEDIFF(DAY, rec.startDate, f.ApptDate) <= 30 THEN rec.startDate ELSE f.ApptDate END
  FROM rec
  JOIN f
    ON rec.rn = f.rn - 1
   AND rec.PatientId = f.PatientId
)
SELECT ApptId, PatientId, ApptDate, Category
FROM rec
ORDER BY PatientId, ApptDate;  

ডিবি <> ফিডাল ডেমো

আউটপুট:

+---------+------------+-------------+----------+
| ApptId  | PatientId  |  ApptDate   | Category |
+---------+------------+-------------+----------+
|      1  |       101  | 2020-01-05  | New      |
|      5  |       101  | 2020-01-25  | FollowUp |
|      6  |       101  | 2020-02-12  | New      |
|      7  |       101  | 2020-02-20  | FollowUp |
|      8  |       101  | 2020-03-30  | New      |
|      9  |       303  | 2020-01-28  | New      |
|     10  |       303  | 2020-02-02  | FollowUp |
|      2  |       505  | 2020-01-06  | New      |
|      3  |       505  | 2020-01-10  | FollowUp |
|      4  |       505  | 2020-01-20  | FollowUp |
+---------+------------+-------------+----------+

কিভাবে এটা কাজ করে:

  1. f - প্রারম্ভিক পয়েন্ট পান (প্রতিটি রোগীআইডির জন্য অ্যাঙ্কর)
  2. পুনরায় - পুনরাবৃত্তি অংশ, যদি বর্তমান মান এবং পূর্বের মধ্যে পার্থক্য হয়> 30 রোগীর আইডের প্রসঙ্গে বিভাগ এবং প্রারম্ভিক বিন্দু পরিবর্তন করে
  3. প্রধান - প্রদর্শন বাছাই ফলাফল

অনুরূপ শ্রেণি:

ওরাকল-এ শর্তসাপেক্ষ SUM - একটি উইন্ডোযুক্ত ফাংশন ক্যাপ করা

সেশন উইন্ডো (আজার স্ট্রিম বিশ্লেষণ)

নির্দিষ্ট শর্তটি সত্য না হওয়া পর্যন্ত মোট চলমান - হালকা আপডেট


অভিযোজ্য বস্তু

উত্পাদনে এই কোডটি কখনও ব্যবহার করবেন না!

তবে অন্য একটি বিকল্প, এটি সিটি ব্যবহারের পাশাপাশি উল্লেখযোগ্য, হ'ল টেম্পল টেবিল ব্যবহার করা এবং "রাউন্ডগুলিতে" আপডেট করা

এটি "একক" রাউন্ডে করা যেতে পারে (উদ্দীপনা আপডেট):

CREATE TABLE Appt_temp (ApptID INT , PatientID INT, ApptDate DATE, Category NVARCHAR(10))

INSERT INTO Appt_temp(ApptId, PatientId, ApptDate)
SELECT ApptId, PatientId, ApptDate
FROM Appt1;

CREATE CLUSTERED INDEX Idx_appt ON Appt_temp(PatientID, ApptDate);

প্রশ্ন:

DECLARE @PatientId INT = 0,
        @PrevPatientId INT,
        @FirstApptDate DATE = NULL;

UPDATE Appt_temp
SET  @PrevPatientId = @PatientId
    ,@PatientId     = PatientID 
    ,@FirstApptDate = CASE WHEN @PrevPatientId <> @PatientId THEN ApptDate
                           WHEN DATEDIFF(DAY, @FirstApptDate, ApptDate)>30 THEN ApptDate
                           ELSE @FirstApptDate
                      END
    ,Category       = CASE WHEN @PrevPatientId <> @PatientId THEN 'New'
                           WHEN @FirstApptDate = ApptDate THEN 'New'
                           ELSE 'FollowUp' 
                      END
FROM Appt_temp WITH(INDEX(Idx_appt))
OPTION (MAXDOP 1);

SELECT * FROM  Appt_temp ORDER BY PatientId, ApptDate;

ডিবি <> ফিডল কুইরকি আপডেট


1
আপনার যুক্তি আমার সাথে খুব মিল। আপনি কোন উল্লেখযোগ্য পার্থক্য বর্ণনা করতে পারেন?
pwilcox

@pwilcox যখন আমি এই উত্তরটি লিখেছিলাম তখন উপস্থিত প্রত্যেকটি সরল সারি_সংখ্যার ব্যবহার করে যা কাজ করে না, এই কারণেই আমি আমার নিজস্ব সংস্করণ সরবরাহ করেছি
লুকাশজ সজোডদা

হ্যাঁ, আমি উত্তরটি দিয়ে খুব দ্রুত ছিলাম। যে মন্তব্য করার জন্য Thx।
ইরদিস

2
আমি বিশ্বাস করি এসকিউএল সার্ভার সঠিকভাবে RANGE x PRECEDINGধারাটি প্রয়োগ না করা পর্যন্ত আরসিটিই এর একমাত্র সমাধান ।
সালমান এ

1
@ এলসিজে কিরকি আপডেটটি "অননুমোদিত" আচরণের উপর ভিত্তি করে এটি কোনও নোটিশ ছাড়াই যে কোনও মুহুর্তে পরিবর্তিত হতে পারে ( red-gate.com/simple-talk/sql/learn-sql-server/… )
লুকাসজ সজোদা

5

আপনি এটি একটি পুনরাবৃত্ত cte দিয়ে করতে পারেন। আপনার প্রথমে প্রতিটি রোগীর মধ্যে অ্যাপটিডেটের মাধ্যমে অর্ডার করা উচিত। এটি মিল-রান-র-এর মাধ্যমে সম্পাদন করা যেতে পারে।

তারপরে, আপনার পুনরাবৃত্তিযোগ্য সিটির অ্যাঙ্কর অংশে, প্রতিটি রোগীর জন্য প্রথম ক্রমটি নির্বাচন করুন, 'নতুন' হিসাবে স্থিতি চিহ্নিত করুন এবং অ্যাপটিডেটকে সর্বাধিক সাম্প্রতিক 'নতুন' রেকর্ডের তারিখ হিসাবে চিহ্নিত করুন।

আপনার পুনরাবৃত্ত cte এর পুনরাবৃত্ত অংশে, পরবর্তী অ্যাপয়েন্টমেন্ট নিয়োগ, বর্তমান অ্যাপয়েন্টমেন্ট এবং সর্বাধিক সাম্প্রতিক 'নতুন' অ্যাপয়েন্টমেন্ট তারিখের মধ্যে দিনের পার্থক্য গণনা করুন। যদি এটি 30 দিনের বেশি হয় তবে এটি 'নতুন' চিহ্নিত করুন এবং সর্বাধিক সাম্প্রতিক নতুন অ্যাপয়েন্টমেন্টের তারিখটি পুনরায় সেট করুন। অন্যথায় এটিকে 'ফলোআপ' হিসাবে চিহ্নিত করুন এবং নতুন অ্যাপয়েন্টমেন্টের তারিখের পরে বিদ্যমান দিনগুলি পেরিয়ে যান।

অবশেষে, বেস ক্যোয়ারিতে, আপনার পছন্দসই কলামগুলি নির্বাচন করুন।

with orderings as (

    select       *, 
                 rn = row_number() over(
                     partition by patientId 
                     order by apptDate
                 ) 
    from         #appt1 a

),

markings as (

    select       apptId, 
                 patientId, 
                 apptDate, 
                 rn, 
                 type = convert(varchar(10),'new'),
                 dateOfNew = apptDate
    from         orderings 
    where        rn = 1

    union all
    select       o.apptId, o.patientId, o.apptDate, o.rn,
                 type = convert(varchar(10),iif(ap.daysSinceNew > 30, 'new', 'follow up')),
                 dateOfNew = iif(ap.daysSinceNew > 30, o.apptDate, m.dateOfNew)
    from         markings m
    join         orderings o 
                     on m.patientId = o.patientId 
                     and m.rn + 1 = o.rn
    cross apply  (select daysSinceNew = datediff(day, m.dateOfNew, o.apptDate)) ap

)

select    apptId, patientId, apptDate, type
from      markings
order by  patientId, rn;

আমার উল্লেখ করা উচিত যে আমি প্রাথমিকভাবে এই উত্তরটি মুছে ফেলেছি কারণ অভিজিৎ খান্ডাগালের উত্তরটি আপনার প্রয়োজনগুলি একটি সহজ ক্যোয়ারী (কিছুটা চালিয়ে যাওয়ার পরে) দিয়ে মনে হয়েছিল। তবে আপনার ব্যবসায়ের প্রয়োজনীয়তা এবং আপনার যুক্ত হওয়া নমুনা ডেটা সম্পর্কে তাঁর কাছে আপনার মন্তব্যে আমি আমার বাতিল করেছিলাম কারণ বিশ্বাস করুন যে এটি আপনার প্রয়োজনগুলি পূরণ করে।


4

আমি নিশ্চিত নই যে আপনি ঠিক এটি প্রয়োগ করেছেন। তবে আরেকটি বিকল্প, এটি সিটি ব্যবহারের পাশাপাশি উল্লেখযোগ্য, হ'ল টেম্পল টেবিল ব্যবহার করা এবং "রাউন্ডগুলিতে" আপডেট করা। সুতরাং আমরা অস্থায়ী টেবিল আপডেট করতে যাচ্ছি যখন সমস্ত স্ট্যাটাসগুলি সঠিকভাবে সেট না করা থাকে এবং পুনরাবৃত্তি উপায়ে ফলাফল তৈরি করে। আমরা কেবল স্থানীয় ভেরিয়েবল ব্যবহার করে পুনরাবৃত্তির সংখ্যা নিয়ন্ত্রণ করতে পারি।

সুতরাং আমরা প্রতিটি পুনরাবৃত্তি দুটি পর্যায়ে বিভক্ত।

  1. নতুন রেকর্ডের নিকটে থাকা সমস্ত ফলোআপ মান সেট করুন। কেবল সঠিক ফিল্টার ব্যবহার করা এটি বেশ সহজ।
  2. স্ট্যাটাস সেট না থাকা বাকী রেকর্ডগুলির জন্য আমরা একই রোগী গ্রুপের সাথে গ্রুপে প্রথমে নির্বাচন করতে পারি। এবং বলুন যে তারা নতুন যেহেতু প্রথম পর্যায়ে প্রক্রিয়াজাত হয়নি।

সুতরাং

CREATE TABLE #Appt2 (ApptID INT, PatientID INT, ApptDate DATE, AppStatus nvarchar(100))

select * from #Appt1
insert into #Appt2 (ApptID, PatientID, ApptDate, AppStatus)
select a1.ApptID, a1.PatientID, a1.ApptDate, null from #Appt1 a1
declare @limit int = 0;

while (exists(select * from #Appt2 where AppStatus IS NULL) and @limit < 1000)
begin
  set @limit = @limit+1;
  update a2
  set
    a2.AppStatus = IIF(exists(
        select * 
        from #Appt2 a 
        where 
          0 > DATEDIFF(day, a2.ApptDate, a.ApptDate) 
          and DATEDIFF(day, a2.ApptDate, a.ApptDate) > -30 
          and a.ApptID != a2.ApptID 
          and a.PatientID = a2.PatientID
          and a.AppStatus = 'New'
          ), 'Followup', a2.AppStatus)
  from #Appt2 a2

  --select * from #Appt2

  update a2
  set a2.AppStatus = 'New'
  from #Appt2 a2 join (select a.*, ROW_NUMBER() over (Partition By PatientId order by ApptId) rn from (select * from #Appt2 where AppStatus IS NULL) a) ar
  on a2.ApptID = ar.ApptID
  and ar.rn = 1

  --select * from #Appt2

end

select * from #Appt2 order by PatientID, ApptDate

drop table #Appt1
drop table #Appt2

হালনাগাদ. লুকাসজ প্রদত্ত মন্তব্যটি পড়ুন। এটি অনেক স্মার্ট পথে। আমি আমার উত্তরটি কেবল একটি ধারণা হিসাবে রেখেছি।


4

আমি বিশ্বাস করি যে পুনরাবৃত্ত হওয়া সাধারণ অভিব্যক্তিটি লুপগুলি এড়িয়ে যাওয়া প্রশ্নের অনুকূলকরণের দুর্দান্ত উপায়, তবে কিছু ক্ষেত্রে এটি খারাপ কার্য সম্পাদন করতে পারে এবং সম্ভব হলে এড়ানো উচিত।

আমি সমস্যাটি সমাধান করার জন্য নীচের কোডটি ব্যবহার করি এবং এটি আরও মূল্যবোধের পরীক্ষার জন্য পরীক্ষিত হয় তবে এটি আপনাকে আপনার আসল ডেটা দিয়ে পরীক্ষা করতে উত্সাহিত করে।

WITH DataSource AS
(
    SELECT *
          ,CEILING(DATEDIFF(DAY, MIN([ApptDate]) OVER (PARTITION BY [PatientID]), [ApptDate]) * 1.0 / 30 + 0.000001) AS [GroupID]
    FROM #Appt1
)
SELECT *
     ,IIF(ROW_NUMBER() OVER (PARTITION BY [PatientID], [GroupID] ORDER BY [ApptDate]) = 1, 'New', 'Followup')
FROM DataSource
ORDER BY [PatientID]
        ,[ApptDate];

এখানে চিত্র বর্ণনা লিখুন

ধারণাটি বেশ সহজ - আমি গ্রুপে রেকর্ডগুলি পৃথক করতে চাই (30 দিন), যার গ্রুপে সবচেয়ে ছোট রেকর্ডটি রয়েছে new, অন্যরা follow ups। বিবৃতিটি কীভাবে নির্মিত হয়েছে তা পরীক্ষা করুন:

SELECT *
      ,DATEDIFF(DAY, MIN([ApptDate]) OVER (PARTITION BY [PatientID]), [ApptDate])
      ,DATEDIFF(DAY, MIN([ApptDate]) OVER (PARTITION BY [PatientID]), [ApptDate]) * 1.0 / 30
      ,CEILING(DATEDIFF(DAY, MIN([ApptDate]) OVER (PARTITION BY [PatientID]), [ApptDate]) * 1.0 / 30 + 0.000001) 
FROM #Appt1
ORDER BY [PatientID]
        ,[ApptDate];

এখানে চিত্র বর্ণনা লিখুন

তাই:

  1. প্রথমত, আমরা প্রতিটি গ্রুপের জন্য প্রথম তারিখ পাচ্ছি এবং বর্তমানের সাথে দিনের মধ্যে পার্থক্য গণনা করছি
  2. তারপরে, আমরা দলগুলি পেতে চাই - * 1.0 / 30যুক্ত হয়
  3. 30, 60, 90, ইত্যাদির মতো আমরা পুরো নম্বর পাচ্ছি এবং আমরা একটি নতুন সময় শুরু করতে চেয়েছিলাম, আমি যোগ করেছি + 0.000001; এছাড়াও, আমরা সিলিং ফাংশনটি ব্যবহার করছি getsmallest integer greater than, or equal to, the specified numeric expression

এটাই. এই জাতীয় গোষ্ঠী থাকা আমরা কেবল ROW_NUMBERআমাদের শুরুর তারিখটি সন্ধান করতে এবং এটিকে তৈরি করতে newএবং বাকী হিসাবে রেখে দিতে ব্যবহার করি follow ups


2
ঠিক আছে, প্রশ্নটি কিছুটা আলাদা এবং এই উত্সাহটি হ'ল ওভারসিম্প্লিফিকেশন। তবে
টমলিং

এটি পারফরম্যান্স সম্পর্কেও। আমি বিশ্বাস করি পুনরাবৃত্ত হওয়া ধীর হওয়া উচিত।
পেয়েছি

3

প্রত্যেককে এবং আইএমএইচও-তে যথাযথ শ্রদ্ধার সাথে,

There is not much difference between While LOOP and Recursive CTE in terms of RBAR

ব্যবহার করার সময় Recursive CTEএবং একসাথে খুব বেশি পারফরম্যান্স লাভ হয় না Window Partition function

Appidহওয়া উচিত int identity(1,1), বা এটি ক্রমবর্ধমান হওয়া উচিত clustered index

অন্যান্য উপকারের পাশাপাশি এটিও নিশ্চিত করে APPDateযে রোগীর সমস্ত ক্রমাগত সারি অবশ্যই বৃহত্তর হতে হবে।

আপনি সহজেই APPIDআপনার ক্যোয়ারিতে এটি খেলতে পারবেন যা inequalityঅপারেটর>>, <পিপিএডে রাখার চেয়ে আরও কার্যকর will ফেলে inequalityমত> অপারেটর, <APPID এসকিউএল অপ্টিমাইজার সাহায্য করবেন।

এছাড়াও টেবিলে দুটি তারিখের কলাম থাকতে হবে

APPDateTime datetime2(0) not null,
Appdate date not null

যেহেতু এটি সর্বাধিক গুরুত্বপূর্ণ সারণীতে সর্বাধিক গুরুত্বপূর্ণ কলামগুলি, তাই খুব বেশি castালাই নয়, রূপান্তর করুন।

তাই Non clustered indexঅ্যাপডেটে তৈরি করা যায়

Create NonClustered index ix_PID_AppDate_App  on APP (patientid,APPDate) include(other column which is not i predicate except APPID)

অন্যান্য স্ক্রিনের ডেটা দিয়ে আমার স্ক্রিপ্টটি পরীক্ষা করুন এবং লেম্মে জানেন যে কোন নমুনা ডেটা এটি কাজ করছে না। এমনকি যদি এটি কাজ না করে তবে আমি নিশ্চিত যে এটি আমার স্ক্রিপ্টের যুক্তিতেই ঠিক করা যেতে পারে।

CREATE TABLE #Appt1 (ApptID INT, PatientID INT, ApptDate DATE)
INSERT INTO #Appt1
SELECT  1,101,'2020-01-05'  UNION ALL
SELECT  2,505,'2020-01-06'  UNION ALL
SELECT  3,505,'2020-01-10'  UNION ALL
SELECT  4,505,'2020-01-20'  UNION ALL
SELECT  5,101,'2020-01-25'  UNION ALL
SELECT  6,101,'2020-02-12'  UNION ALL
SELECT  7,101,'2020-02-20'  UNION ALL
SELECT  8,101,'2020-03-30'  UNION ALL
SELECT  9,303,'2020-01-28'  UNION ALL
SELECT  10,303,'2020-02-02' 

;With CTE as
(
select a1.* ,a2.ApptDate as NewApptDate
from #Appt1 a1
outer apply(select top 1 a2.ApptID ,a2.ApptDate
from #Appt1 A2 
where a1.PatientID=a2.PatientID and a1.ApptID>a2.ApptID 
and DATEDIFF(day,a2.ApptDate, a1.ApptDate)>30
order by a2.ApptID desc )A2
)
,CTE1 as
(
select a1.*, a2.ApptDate as FollowApptDate
from CTE A1
outer apply(select top 1 a2.ApptID ,a2.ApptDate
from #Appt1 A2 
where a1.PatientID=a2.PatientID and a1.ApptID>a2.ApptID 
and DATEDIFF(day,a2.ApptDate, a1.ApptDate)<=30
order by a2.ApptID desc )A2
)
select  * 
,case when FollowApptDate is null then 'New' 
when NewApptDate is not null and FollowApptDate is not null 
and DATEDIFF(day,NewApptDate, FollowApptDate)<=30 then 'New'
else 'Followup' end
 as Category
from cte1 a1
order by a1.PatientID

drop table #Appt1

3

যদিও প্রশ্নটিতে এটি সুস্পষ্টভাবে সমাধান করা হয়নি, তবে নির্ধারণ করা সহজ যে অ্যাপয়েন্টমেন্টের তারিখগুলি কেবল 30-দিনের গ্রুপ দ্বারা শ্রেণিবদ্ধ করা যায় না। এটি কোনও ব্যবসায়িক ধারণা তৈরি করে না। এবং আপনি অ্যাপটি আইডিও ব্যবহার করতে পারবেন না। আজকের জন্য একটি নতুন অ্যাপয়েন্টমেন্ট করতে পারেন2020-09-06। এই সমস্যাটি আমি কীভাবে সম্বোধন করছি তা এখানে। প্রথমে প্রথম অ্যাপয়েন্টমেন্ট পান, তারপরে প্রতিটি অ্যাপয়েন্টমেন্ট এবং প্রথম অ্যাপের মধ্যে তারিখের পার্থক্য গণনা করুন। যদি এটি 0 হয় তবে 'নতুন' এ সেট করুন। যদি <= 30 'ফলোআপ' হয়। যদি> 30 হয় তবে 'অনিশ্চিত' হিসাবে সেট করুন এবং আর 'অনিশ্চিত' না হওয়া পর্যন্ত পরবর্তী রাউন্ড চেক করুন। এবং তার জন্য, আপনার সত্যিকার অর্থে কিছুক্ষণ লুপ দরকার, তবে এটি প্রতিটি অ্যাপয়েন্টমেন্টের তারিখের মধ্য দিয়ে লুপ করে না, কেবল কয়েকটি ডেটাসেট। আমি ফাঁসির পরিকল্পনাটি পরীক্ষা করেছিলাম। যদিও এখানে কেবল 10 টি সারি রয়েছে, পুনরাবৃত্ত সিটিই ব্যবহারের তুলনায় ক্যোয়ারী ব্যয়টি উল্লেখযোগ্যভাবে কম তবে লুকাস স্জোজদা সংযোজন পদ্ধতির চেয়ে কম নয়।

IF OBJECT_ID('tempdb..#TEMPTABLE') IS NOT NULL DROP TABLE #TEMPTABLE
SELECT ApptID, PatientID, ApptDate
    ,CASE WHEN (DATEDIFF(DAY, MIN(ApptDate) OVER (PARTITION BY PatientID), ApptDate) = 0) THEN 'New' 
    WHEN (DATEDIFF(DAY, MIN(ApptDate) OVER (PARTITION BY PatientID), ApptDate) <= 30) THEN 'Followup'
    ELSE 'Undecided' END AS Category
INTO #TEMPTABLE
FROM #Appt1

WHILE EXISTS(SELECT TOP 1 * FROM #TEMPTABLE WHERE Category = 'Undecided') BEGIN
    ;WITH CTE AS (
        SELECT ApptID, PatientID, ApptDate 
            ,CASE WHEN (DATEDIFF(DAY, MIN(ApptDate) OVER (PARTITION BY PatientID), ApptDate) = 0) THEN 'New' 
            WHEN (DATEDIFF(DAY, MIN(ApptDate) OVER (PARTITION BY PatientID), ApptDate) <= 30) THEN 'Followup'
            ELSE 'Undecided' END AS Category    
        FROM #TEMPTABLE
        WHERE Category = 'Undecided'
    )
    UPDATE #TEMPTABLE
    SET Category = CTE.Category
    FROM #TEMPTABLE t
        LEFT JOIN CTE ON CTE.ApptID = t.ApptID
    WHERE t.Category = 'Undecided'
END

SELECT ApptID, PatientID, ApptDate, Category 
FROM #TEMPTABLE

2

আমি আশা করি এটা তোমাকে সাহায্য করবে।

WITH CTE AS
(
    SELECT #Appt1.*, RowNum = ROW_NUMBER() OVER (PARTITION BY PatientID ORDER BY ApptDate, ApptID) FROM #Appt1
)

SELECT A.ApptID , A.PatientID , A.ApptDate ,
Expected_Category = CASE WHEN (DATEDIFF(MONTH, B.ApptDate, A.ApptDate) > 0) THEN 'New' 
WHEN (DATEDIFF(DAY, B.ApptDate, A.ApptDate) <= 30) then 'Followup' 
ELSE 'New' END
FROM CTE A
LEFT OUTER JOIN CTE B on A.PatientID = B.PatientID 
AND A.rownum = B.rownum + 1
ORDER BY A.PatientID, A.ApptDate

পাঠযোগ্য বিন্যাসে কোড সম্পাদনা করার জন্য @ x00 ধন্যবাদ, আমি উত্তর পোস্ট করতে আমার সেলফোনটি ব্যবহার করছি যাতে সঠিক ইন্ডেন্টেশন দিতে সক্ষম হয় নি।
অভিজিৎ খান্ডাগলে

আমি মনে করি এটি সংক্ষেপে সঠিক উত্তর। তবে এটি একটি নিম্ন মানের উত্তর যা এটি ব্যাখ্যা করা হয়নি এবং অভ্যন্তরীণ অংশের কোনও পরিবর্তন যখন ঠিকঠাক করবে তখন কোডটির অপ্রয়োজনীয় বাহ্যিক জিজ্ঞাসা রয়েছে। আপনি যদি এই সমস্যাগুলি সমাধান করতে পারেন তবে আমি আপনাকে ভোট দিয়ে খুশি হব।
pwilcox

1
@ প্লুইকক্স, মূল্যবান পরামর্শের জন্য ধন্যবাদ, আমি উত্তরটি সম্পাদনা করেছি এবং এখনই পোস্ট করেছি। যেহেতু আমি ভ্রমণ করছি এবং আমার সাথে ল্যাপটপ নেই, আমি এক-দু'দিনের মধ্যে ব্যাখ্যা পোস্ট করব।
অভিজিৎ খনদাগলে

1
@ অভিজিৎখণ্ডগলে এটি ব্যবসায়ের প্রয়োজনীয়তা পুরোপুরি পূরণ করে না। আমি প্রশ্নে একটি ব্যর্থ পরিস্থিতি যুক্ত করেছি। 303 রোগীর জন্য, 2 শে ফেব্রুয়ারী অ্যাপয়েন্টমেন্ট ফলোআপ করা উচিত; তবে আপনার জিজ্ঞাসাটি এটি "নতুন"
এলসিজে

1

আপনি একটি Caseবিবৃতি ব্যবহার করতে পারেন ।

select 
      *, 
      CASE 
          WHEN DATEDIFF(d,A1.ApptDate,A2.ApptDate)>30 THEN 'New' 
          ELSE 'FollowUp' 
      END 'Category'
from 
      (SELECT PatientId, MIN(ApptId) 'ApptId', MIN(ApptDate) 'ApptDate' FROM #Appt1 GROUP BY PatientID)  A1, 
      #Appt1 A2 
where 
     A1.PatientID=A2.PatientID AND A1.ApptID<A2.ApptID

প্রশ্নটি হচ্ছে, প্রাথমিক অ্যাপয়েন্টমেন্টের ভিত্তিতে এই বিভাগটি বরাদ্দ করা উচিত, বা একের আগে? অর্থাৎ, যদি কোনও রোগীর তিনটি অ্যাপয়েন্টমেন্ট থাকে তবে আমাদের তৃতীয় অ্যাপয়েন্টমেন্টটি প্রথম বা দ্বিতীয়টির সাথে তুলনা করা উচিত?

আপনি সমস্যাটি প্রথম উল্লেখ করেছেন, যা আমি উত্তর দিয়েছি। যদি এটি না হয়, আপনি ব্যবহার করতে চাইবেন lag

এছাড়াও, মনে রাখবেন যে DateDiffসাপ্তাহিক ছুটির ক্ষেত্রে ব্যতিক্রম হয় না। যদি এটি কেবল সপ্তাহের দিন হওয়া উচিত তবে আপনাকে নিজের স্কেলার-মূল্যবান ফাংশন তৈরি করতে হবে।


1
এটি দুটি অনুক্রমিক অ্যাপয়েন্টমেন্টগুলির সাথে লিঙ্ক দেয় না, এটি নীচের সমস্ত অ্যাপয়েন্টমেন্টের সাথে 1 টি সংযুক্ত করে এবং তাদের সবার জন্য দিনের মধ্যে গণনা করে। আপনি এইভাবে অনেকগুলি রেকর্ড ফিরিয়ে আনতে পারবেন, কারণ অ্যাপ্লিকেশন 1 এর এখন 2, 3, 4 এর সাথে সম্পর্ক রয়েছে, অ্যাপ্লিকেশন 2 এর সাথে 3, 4 ... এর একটি সম্পর্ক রয়েছে ...
স্টেইনবার্গ

ভাল যুক্তি. আমি আমার উত্তরটি এ 1-এর জন্য সাব-সাবলেট করতে আপডেট করেছি।
ব্যবহারকারী

1
এটি প্রত্যাশিত ফলাফল দেয় না। 20 ফেব্রুয়ারির অ্যাপয়েন্টমেন্ট "ফলোআপ" হওয়া উচিত
এলসিজে

প্রশ্নের অস্পষ্টতা ... পোস্টারের বিবরণটি হ'ল: "কোনও অ্যাপয়েন্টমেন্ট (রোগীর জন্য) প্রথম অ্যাপয়েন্টমেন্টের 30 দিনের মধ্যে (সেই রোগীর) ফলোআপ হয় 30 30 দিন পরে, অ্যাপয়েন্টমেন্টটি আবার" নতুন "30 "ফলোআপ" হয়ে যান। " 5 ই জানুয়ারী অবশ্যই 20 শে ফেব্রুয়ারি, অর্থাৎ নতুন থেকে 30 দিনের বেশি দূরে। তবে 12 শে ফেব্রুয়ারি থেকে 30 দিনের দূরে নয়। আমি কী লিখেছি তার একটি সমাধান অফার করছি, টেবিল সরবরাহ করা হয়নি। যদি ব্যবহারকারী টেবিলটি সরবরাহ করে তবে তা সারিবদ্ধ করতে চান, তবে তাদের পিছনে লেগ ব্যবহার করা উচিত। তাদেরও পরিষ্কার করা উচিত ...
ব্যবহারকারী

1

ল্যাগ ফাংশন ব্যবহার করে


select  apptID, PatientID , Apptdate ,  
    case when date_diff IS NULL THEN 'NEW' 
         when date_diff < 30 and (date_diff_2 IS NULL or date_diff_2 < 30) THEN  'Follow Up'
         ELSE 'NEW'
    END AS STATUS FROM 
(
select 
apptID, PatientID , Apptdate , 
DATEDIFF (day,lag(Apptdate) over (PARTITION BY PatientID order by ApptID asc),Apptdate) date_diff ,
DATEDIFF(day,lag(Apptdate,2) over (PARTITION BY PatientID order by ApptID asc),Apptdate) date_diff_2
  from #Appt1
) SRC

ডেমো -> https://rextester.com/TNW43808


2
এটি বর্তমানের নমুনা ডেটাতে কাজ করে তবে ভিন্ন নমুনার ডেটা দেওয়া ভুল ফলাফল পেতে পারে। এমনকি যদি আপনি ফাংশনটির কলাম apptDateহিসাবে ব্যবহার করেন (যা আপনাকে সত্যই আইডি হিসাবে দেখা উচিত তবে এটি কোনও কিছুর গ্যারান্টি নয়) তবে আরও ফলোআপ অ্যাপয়েন্টমেন্টগুলি প্রবর্তন করে এটি সহজেই ভাঙ্গা যায়। উদাহরণস্বরূপ এই রেক্সটেস্টার ডেমোটি দেখুন । যদিও ভাল চেষ্টা করুন ...order bylag
জোহর পিলড

ধন্যবাদ. আইডির পরিবর্তে তারিখ ব্যবহার করা উচিত ছিল। তবে এটি কেন অ্যাপটিআইডি = 6 25.01.2020 - 12.02.2020 -> 18 দিন -> ফলোআপের জন্য ভুল।
দিগ্বিজয় এস

2
কারণ এটি একটি Newএবং একটি হওয়া উচিত FollowUp। এই রোগীর প্রথম অ্যাপয়েন্টমেন্টের 30 দিনেরও বেশি সময় ... প্রতিটি Newঅ্যাপয়েন্টমেন্টের পরে আপনার 30 দিন গণনা করা উচিত এবং তারপরে Newআবার ব্যবহার করা উচিত ...
জোহর প্লেড

হ্যাঁ. ধন্যবাদ. :( বৈধ তারিখের সময় যাচাই করার জন্য একটি নতুন তৈরি করা দরকার
दिग्বিজয় এস

1
with cte
as
(
select 
tmp.*, 
IsNull(Lag(ApptDate) Over (partition by PatientID Order by  PatientID,ApptDate),ApptDate) PriorApptDate
 from #Appt1 tmp
)
select 
PatientID, 
ApptDate, 
PriorApptDate, 
DateDiff(d,PriorApptDate,ApptDate) Elapsed,
Case when DateDiff(d,PriorApptDate,ApptDate)>30 
or DateDiff(d,PriorApptDate,ApptDate)=0 then 'New' else 'Followup'   end Category   from cte

আমার সঠিক। লেখকগুলি ভুল ছিল, শেষ হয়েছে দেখুন

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.