শেষবারের জন্য একটি মান পরিবর্তিত হয়েছে তা চেষ্টা করার চেষ্টা করছেন


26

আমার একটি টেবিল রয়েছে যার আইডি, একটি মান এবং একটি তারিখ রয়েছে। এই টেবিলটিতে অনেকগুলি আইডি, মান এবং তারিখ রয়েছে।

এই টেবিলে পর্যায়ক্রমে রেকর্ডগুলি .োকানো হয়। আইডি সর্বদা একই থাকে তবে মাঝে মাঝে মানটি পরিবর্তিত হয়।

আমি কীভাবে এমন কোনও ক্যোয়ারী লিখব যা আমাকে আইডি প্লাস দেবে এবং সাম্প্রতিক সময়ে মানটি বদলেছে? দ্রষ্টব্য: মান সর্বদা বৃদ্ধি পাবে।

এই নমুনা তথ্য থেকে:

  Create Table Taco
 (  Taco_ID int,
    Taco_value int,
    Taco_date datetime)

Insert INTO Taco 
Values (1, 1, '2012-07-01 00:00:01'),
        (1, 1, '2012-07-01 00:00:02'),
        (1, 1, '2012-07-01 00:00:03'),
        (1, 1, '2012-07-01 00:00:04'),
        (1, 2, '2012-07-01 00:00:05'),
        (1, 2, '2012-07-01 00:00:06'),
        (1, 2, '2012-07-01 00:00:07'),
        (1, 2, '2012-07-01 00:00:08')

ফলাফলটি হওয়া উচিত:

Taco_ID      Taco_date
1            2012-07-01 00:00:05

(কারণ 00:05 শেষ সময় Taco_Valueপরিবর্তন হয়েছিল ))


2
আমি ধরে নিলাম tacoখাবারের সাথে কিছু করার নেই?
কেরমিট

5
আমি ক্ষুধার্ত এবং কিছু টাকো খেতে চাই। স্যাম্পল টেবিলের জন্য কেবল একটি নাম প্রয়োজন।
স্কেলস্যান্ডউইচেস

8
আপনি কি একইভাবে আপনার ব্যবহারকারীর নামটি বেছে নিয়েছেন?
মার্টিন স্মিথ

1
বেশ সম্ভব।
স্কেলস্যান্ডভিচস

উত্তর:


13

এই দুটি প্রশ্নের অনুমানের উপর নির্ভর করে যা Taco_valueসময়ের সাথে সর্বদা বৃদ্ধি পায়।

;WITH x AS
(
  SELECT Taco_ID, Taco_date,
    dr = ROW_NUMBER() OVER (PARTITION BY Taco_ID, Taco_Value ORDER BY Taco_date),
    qr = ROW_NUMBER() OVER (PARTITION BY Taco_ID ORDER BY Taco_date)
  FROM dbo.Taco
), y AS
(
  SELECT Taco_ID, Taco_date,
    rn = ROW_NUMBER() OVER (PARTITION BY Taco_ID, dr ORDER BY qr DESC)
  FROM x WHERE dr = 1
)
SELECT Taco_ID, Taco_date
FROM y 
WHERE rn = 1;

কম উইন্ডো ফাংশন পাগলামি সহ একটি বিকল্প:

;WITH x AS
(
  SELECT Taco_ID, Taco_value, Taco_date = MIN(Taco_date)
  FROM dbo.Taco
  GROUP BY Taco_ID, Taco_value
), y AS
(
  SELECT Taco_ID, Taco_date, 
    rn = ROW_NUMBER() OVER (PARTITION BY Taco_ID ORDER BY Taco_date DESC)
  FROM x
)
SELECT Taco_ID, Taco_date FROM y WHERE rn = 1;

এসকিউএলফিডেলে উদাহরণ


হালনাগাদ

যারা ট্র্যাক রাখছেন তাদের পক্ষে বিতর্ক ছিল যে যদি Taco_valueকখনও পুনরাবৃত্তি করা যায় তবে কী হয় । এটি যদি 1 থেকে 2 এবং পরে প্রদত্ত যে কোনওটির জন্য 1 এ ফিরে যেতে পারে Taco_IDতবে কোয়েরিগুলি কাজ করবে না। এই মামলার সমাধান এখানে রয়েছে, যদিও এটি ফাঁক এবং দ্বীপপুঞ্জের কৌশলটি না হলেও এটিজিক বেন-গানের মতো কেউ স্বপ্ন দেখতে সক্ষম হতে পারে, এবং এটি অপির দৃশ্যের সাথে প্রাসঙ্গিক না হলেও - এটি হতে পারে ভবিষ্যতের পাঠকের সাথে প্রাসঙ্গিক। এটি কিছুটা জটিল, এবং আমি একটি অতিরিক্ত ভেরিয়েবলও যুক্ত করেছিলাম - Taco_IDযা কেবল কখনও একটি রয়েছে Taco_value

আপনি যদি এমন কোনও আইডির জন্য প্রথম সারিটি অন্তর্ভুক্ত করতে চান যেখানে পুরো সেটটিতে কোনও মানই বদলায় না:

;WITH x AS
(
  SELECT *, rn = ROW_NUMBER() OVER 
    (PARTITION BY Taco_ID ORDER BY Taco_date DESC)
  FROM dbo.Taco
), rest AS (SELECT * FROM x WHERE rn > 1)
SELECT  
  main.Taco_ID, 
  Taco_date = MIN(CASE 
    WHEN main.Taco_value = rest.Taco_value 
    THEN rest.Taco_date ELSE main.Taco_date 
  END)
FROM x AS main LEFT OUTER JOIN rest
ON main.Taco_ID = rest.Taco_ID AND rest.rn > 1
WHERE main.rn = 1
AND NOT EXISTS 
(
  SELECT 1 FROM rest AS rest2
   WHERE Taco_ID = rest.Taco_ID
   AND rn < rest.rn
   AND Taco_value <> rest.Taco_value
) 
GROUP BY main.Taco_ID;

আপনি যদি এই সারিগুলি বাদ দিতে চান তবে এটি কিছুটা জটিল, তবে এখনও সামান্য পরিবর্তনগুলি:

;WITH x AS
(
  SELECT *, rn = ROW_NUMBER() OVER 
    (PARTITION BY Taco_ID ORDER BY Taco_date DESC)
  FROM dbo.Taco
), rest AS (SELECT * FROM x WHERE rn > 1)
SELECT 
  main.Taco_ID, 
  Taco_date = MIN(
  CASE 
    WHEN main.Taco_value = rest.Taco_value 
    THEN rest.Taco_date ELSE main.Taco_date 
  END)
FROM x AS main INNER JOIN rest -- ***** change this to INNER JOIN *****
ON main.Taco_ID = rest.Taco_ID AND rest.rn > 1
WHERE main.rn = 1
AND NOT EXISTS
(
  SELECT 1 FROM rest AS rest2
   WHERE Taco_ID = rest.Taco_ID
   AND rn < rest.rn
   AND Taco_value <> rest.Taco_value
)
AND EXISTS -- ***** add this EXISTS clause ***** 
(
  SELECT 1 FROM rest AS rest2
   WHERE Taco_ID = rest.Taco_ID
   AND Taco_value <> rest.Taco_value
)
GROUP BY main.Taco_ID;

আপডেট করা এসকিউএলফিডাল উদাহরণ


আমি ওভারের সাথে কিছু উল্লেখযোগ্য পারফরম্যান্সের সমস্যাগুলি লক্ষ্য করেছি তবে আমি এটি কয়েকবার ব্যবহার করেছি এবং এটি সম্ভবত খারাপ লিখছি। কিছু লক্ষ্য করেছেন?
কেনেথ ফিশার

1
@ কেনেথফিশার বিশেষত ওভারের সাথে নয়। অন্য যে কোনও কিছুর মতো, কোয়েরি রচনাগুলি সঠিকভাবে কাজ করতে অন্তর্নিহিত স্কিমা / সূচীর উপর নির্ভর করে। একটি অতিরিক্ত ধারা যে পার্টিশনগুলি গ্রুপ বাই হিসাবে একই সমস্যায় ভুগবে।
অ্যারন বারট্র্যান্ড

@ কেনেথফিশার দয়া করে একক, বিচ্ছিন্ন পর্যবেক্ষণগুলি থেকে বিস্তৃত, সুস্পষ্ট সিদ্ধান্তগুলি না আনতে সাবধান হন। আমি সিটিইগুলির বিরুদ্ধে একই যুক্তি দেখছি - "ভাল, আমি একবার এই পুনরাবৃত্ত সিটিই পেয়েছিলাম এবং এর অভিনয়টি চুষে ফেলেছে। তাই আমি আর সিটিই ব্যবহার করি না।"
অ্যারন বারট্র্যান্ড

ঐ জন্যই আমি জিজ্ঞাসা করেছিলাম. আমি এটি একরকম বা অন্যভাবে বলার জন্য যথেষ্ট পরিমাণে ব্যবহার করি নি, তবে আমি কয়েকবার এটি ব্যবহার করেছি আমি একটি সিটিইর সাথে আরও ভাল পারফরম্যান্স পেতে সক্ষম হয়েছি। আমি যদিও এটি নিয়ে খেলা চালিয়ে যাব।
কেনেথ ফিশার

@ অ্যারোনবার্ট্রান্ড আমি মনে করি না যে এগুলি valueআবার প্রকাশিত হলে এগুলি কার্যকর হবে : ফিডল
ইপারকিউবᵀᴹ

13

মূলত, এটি কোনও টার্নযুক্ত টেবিল ছাড়াই একক নির্বাচনকে তারিনের পরামর্শ "সংশ্লেষিত":

SELECT DISTINCT
  Taco_ID,
  Taco_date = MAX(MIN(Taco_date)) OVER (PARTITION BY Taco_ID)
FROM Taco
GROUP BY
  Taco_ID,
  Taco_value
;

দ্রষ্টব্য: এই সমাধানটি Taco_valueকেবলমাত্র বৃদ্ধি করতে পারে এমন শর্তকে বিবেচনা করে । (আরও Taco_valueপ্রকৃতপক্ষে , এটি ধরে নেওয়া হয় যে আগের মানটিতে আর পরিবর্তন করা যাবে না - লিঙ্কিত উত্তর হিসাবে একই, আসলে))

প্রশ্নের জন্য একটি এসকিউএল ফিডল ডেমো: http://sqlfiddle.com/#!3/91368/2


7
ওহ, নেস্টেড MAX / MIN। মন নীচের দিকে +1
অ্যারোন বার্ট্র্যান্ড

7

ফলাফল দুটি পেতে আপনার সামগ্রিক min()এবং max()সামগ্রিক ফাংশন সক্ষম হওয়া উচিত :

select t1.Taco_ID, MAX(t1.taco_date) Taco_Date
from taco t1
inner join
(
    select MIN(taco_date) taco_date,
        Taco_ID, Taco_value
    from Taco
    group by Taco_ID, Taco_value
) t2
    on t1.Taco_ID = t2.Taco_ID
    and t1.Taco_date = t2.taco_date
group by t1.Taco_Id

ডেমো সহ এসকিউএল ফিডল দেখুন


5

আর একটি উত্তর যা এই মানগুলির উপর ভিত্তি করে তৈরি হয় যে মানগুলি আবার দেখা দেয় না (এটি মূলত @ হারুনের ক্যোয়ারী 2, একটি কম নীচে ঘনীভূত):

;WITH x AS
(
  SELECT 
    Taco_ID, Taco_value, 
    Rn = ROW_NUMBER() OVER (PARTITION BY Taco_ID
                            ORDER BY MIN(Taco_date) DESC),
    Taco_date = MIN(Taco_date) 
  FROM dbo.Taco
  GROUP BY Taco_ID, Taco_value
)
SELECT Taco_ID, Taco_value, Taco_date
FROM x 
WHERE Rn = 1 ;

পরীক্ষায়: এসকিউএল-ফিডল


এবং আরও সাধারণ সমস্যার একটি উত্তর, যেখানে মানগুলি আবার প্রদর্শিত হতে পারে:

;WITH x AS
(
  SELECT 
    Taco_ID, Taco_value, 
    Rn = ROW_NUMBER() OVER (PARTITION BY Taco_ID
                            ORDER BY MAX(Taco_date) DESC),    
    Taco_date = MAX(Taco_date) 
  FROM dbo.Taco
  GROUP BY Taco_ID, Taco_value
)
SELECT t.Taco_ID, Taco_date = MIN(t.Taco_date)
FROM x
  JOIN dbo.Taco t
    ON  t.Taco_ID = x.Taco_ID
    AND t.Taco_date > x.Taco_date
WHERE x.Rn = 2 
GROUP BY t.Taco_ID ;

(বা CROSS APPLYএর সাথে সম্পর্কিত সমস্ত সারি ব্যবহার করে valueদেখানো হয়েছে):

;WITH x AS
(
  SELECT 
    Taco_ID, Taco_value, 
    Rn = ROW_NUMBER() OVER (PARTITION BY Taco_ID
                            ORDER BY MAX(Taco_date) DESC),    
    Taco_date = MAX(Taco_date) 
  FROM dbo.Taco
  GROUP BY Taco_ID, Taco_value
)
SELECT t.*
FROM x
  CROSS APPLY 
  ( SELECT TOP (1) *
    FROM dbo.Taco t
    WHERE t.Taco_ID = x.Taco_ID
      AND t.Taco_date > x.Taco_date
    ORDER BY t.Taco_date
  ) t
WHERE x.Rn = 2 ;

পরীক্ষা করুন: এসকিউএল-ফিডল -২


আরও সাধারণ সমস্যার জন্য পরামর্শগুলি এমন কোনও আইডিগুলির জন্য কার্যকর হয় না যার কোনও পরিবর্তন নেই। মূল সেটটিতে ডামি এন্ট্রি যুক্ত করে (যেমন কিছু dbo.Taco UNION ALL SELECT DISTINCT Taco_ID, NULL AS Taco_value, '19000101' AS Taco_date) ঠিক করা যায়।
অ্যান্ড্রি এম

@ অ্যান্ড্রিএম আমি জানি আমি ধরে নিয়েছি যে "পরিবর্তন" এর অর্থ কমপক্ষে 2 টি মান থাকলে তারা ফলাফল চায়, ওপি স্পষ্ট করে দেয় না (এবং কারণ এটি লিখতে সহজ ছিল :)
ypercubeᵀᴹ

2

নমুনা কাঠামো এবং ডেটা সরবরাহের জন্য এফওয়াইআই +1। কেবলমাত্র আমি যা জানতে চেয়েছি তা হ'ল সেই ডেটার জন্য প্রত্যাশিত আউটপুট।

সম্পাদনা: এইটি আমার বাদাম চালাচ্ছে। আমি কেবল নতুন ছিলাম এটি করার একটি "সহজ" উপায়। আমি ভুল সমাধানগুলি থেকে মুক্তি পেয়েছি এবং আমি বিশ্বাস করি যে এটি সঠিক। এখানে @ ব্লুয়েফিটের অনুরূপ একটি সমাধান রয়েছে তবে এটি @ অ্যারোনবার্ট্র্যান্ড যে পরীক্ষাগুলি দিয়েছিল তা কভার করে।

;WITH TacoMin AS (SELECT Taco_ID, Taco_value, MIN(Taco_date) InitialValueDate
                FROM Taco
                GROUP BY Taco_ID, Taco_value)
SELECT Taco_ID, MAX(InitialValueDate)
FROM TacoMin
GROUP BY Taco_ID

2
ওপি আরও সাম্প্রতিক তারিখের জন্য জিজ্ঞাসা করবে না, তিনি valueপরিবর্তনগুলি কখন জিজ্ঞাসা করেন ।
ypercubeᵀᴹ

আহ, আমি আমার ভুল দেখতে পাচ্ছি। আমি একটি উত্তর কাজ করেছিলাম, তবে এটি @ হারুনের মতোই এটির পোস্ট করার কোনও অর্থ নেই।
কেনেথ ফিশার

1

কেন কেবল ল্যাগ মান এবং সীসা মানের পার্থক্য পাবেন না? পার্থক্যটি যদি শূন্য হয় তবে এটি পরিবর্তন হয় নি, এটি শূন্য নয়, তবে এটি পরিবর্তন হয়েছিল। এটি একটি সাধারণ ক্যোয়ারিতে করা যেতে পারে:

-- example gives the times the value changed in the last 24 hrs
SELECT
    LastUpdated, [DiffValue]
FROM (
  SELECT
      LastUpdated,
      a.AboveBurdenProbe1TempC - coalesce(lag(a.AboveBurdenProbe1TempC) over (order by ProcessHistoryId), 0) as [DiffValue]
  FROM BFProcessHistory a
  WHERE LastUpdated > getdate() - 1
) b
WHERE [DiffValue] <> 0
ORDER BY LastUpdated ASC

lag...বিশ্লেষণাত্মক ফাংশন কেবল "সম্প্রতি" SQL সার্ভার 2012 সালে চালু করা হয় মূল প্রশ্ন এসকিউএল সার্ভার 2008 R2 উপর একটি সমাধান চাইছে। আপনার সমাধান এসকিউএল সার্ভার ২০০৮ আর 2 এর জন্য কাজ করবে না।
জন ওরফে হট 2 ইউজ

-1

এটি কি নীচের মতো সহজ হতে পারে?

       SELECT taco_id, MAX(
             CASE 
                 WHEN taco_value <> MAX(taco_value) 
                 THEN taco_date 
                 ELSE null 
             END) AS last_change_date

টাকো_ভ্যালু সবসময় বৃদ্ধি পায়?

পিএস আমি নিজেকে বেশ প্রাথমিকভাবে এসকিউএল করি তবে ধীরে ধীরে তবে অবশ্যই শিখছি।


1
এসকিউএল সার্ভারে এটি ত্রুটি দেয়। Cannot perform an aggregate function on an expression containing an aggregate or a subquery
মার্টিন স্মিথ

2
মার্টিনের মন্তব্যে একটি বক্তব্য যুক্ত করা: আপনি যদি কেবল পরীক্ষিত কোড পোস্ট করেন তবে আপনি নিরাপদ দিকে আছেন। আপনি যদি নিজের সাধারণ খেলার মাঠ থেকে দূরে থাকেন তবে একটি সহজ উপায় sqlfiddle.com এ যেতে পারে ।
dezso
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.