নিকটতম মানগুলি খুঁজতে এসকিউএল সার্ভারে কীভাবে একটি কোয়েরি লিখবেন


16

ধরা যাক যে আমার একটি সারণীতে নিম্নলিখিত সংখ্যার মান রয়েছে

32
11
15
123
55
54
23
43
44
44
56
23

ঠিক আছে, তালিকাটি যেতে পারে; এটা কোন ব্যাপার না। এখন আমি এই টেবিলটি জিজ্ঞাসা করতে চাই এবং আমি একটি নির্দিষ্ট সংখ্যার ফিরিয়ে দিতে চাই closest records। ধরা যাক আমি 32 টি সংখ্যার নিকটতম রেকর্ড ম্যাচ ফিরিয়ে দিতে চাই I আমি কি এটি দক্ষতার সাথে অর্জন করতে পারি?

এটি এসকিউএল সার্ভার 2014 এ রয়েছে।

উত্তর:


21

কলামটি সূচিবদ্ধ বলে ধরে নিলে যুক্তিসঙ্গতভাবে দক্ষ হওয়া উচিত।

10 টি সারি দুটি সন্ধান এবং তারপরে এক ধরণের (অবধি) 20 ফিরে আসল।

WITH CTE
     AS ((SELECT TOP 10 *
          FROM   YourTable
          WHERE  YourCol > 32
          ORDER  BY YourCol ASC)
         UNION ALL
         (SELECT TOP 10 *
          FROM   YourTable
          WHERE  YourCol <= 32
          ORDER  BY YourCol DESC))
SELECT TOP 10 *
FROM   CTE
ORDER  BY ABS(YourCol - 32) ASC 

(যেমন নীচের মতো সম্ভাব্য কিছু)

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

অথবা অন্য সম্ভাবনা (এটি সর্বাধিক 10 এ সাজানো সারিগুলির সংখ্যা হ্রাস করে)

WITH A
     AS (SELECT TOP 10 *,
                       YourCol - 32 AS Diff
         FROM   YourTable
         WHERE  YourCol > 32
         ORDER  BY Diff ASC, YourCol ASC),
     B
     AS (SELECT TOP 10 *,
                       32 - YourCol AS Diff
         FROM   YourTable
         WHERE  YourCol <= 32
         ORDER  BY YourCol DESC),
     AB
     AS (SELECT *
         FROM   A
         UNION ALL
         SELECT *
         FROM   B)
SELECT TOP 10 *
FROM   AB
ORDER  BY Diff ASC

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

নোট: উপরের এক্সিকিউশন পরিকল্পনাটি ছিল সাধারণ টেবিল সংজ্ঞার জন্য

CREATE TABLE [dbo].[YourTable](
    [YourCol] [int] NOT NULL CONSTRAINT [SomeIndex] PRIMARY KEY CLUSTERED 
)

প্রযুক্তিগতভাবে, নীচের শাখায় বাছাই করার দরকার নেই যেহেতু এটি ডিফ দ্বারা আদেশ করা হয়েছিল, এবং দুটি আদেশযুক্ত ফলাফলকে মার্জ করা সম্ভব হবে। তবে আমি সেই পরিকল্পনাটি পেতে পারি নি।

ক্যোয়ারীটি কেবলমাত্র ORDER BY Diff ASC, YourCol ASCনয় ORDER BY YourCol ASC, কারণ পরিকল্পনার শীর্ষ শাখায় বাছাই থেকে মুক্তি পাওয়ার জন্য এটি কাজ শেষ করেছিল। আমার দ্বিতীয় গৌণ কলামটি যুক্ত করা দরকার (যদিও এটি ফলাফল হিসাবে কখনই পরিবর্তন করে নাYourCol একই ডিফের সাথে সমস্ত মানের জন্য একই হবে) সুতরাং এটি কোনও বাছাই না করেই মার্জ জয় (কনটেস্টেশন) এর মধ্য দিয়ে যায়।

এসকিউএল সার্ভারটি অনুমান করতে সক্ষম বলে মনে হয় যে এক্সে সূচকগুলি আরোহী ক্রমে সন্ধান করা X + Y দ্বারা অর্ডার করা সারি সরবরাহ করবে এবং কোনও সাজানোর প্রয়োজন নেই। তবে এটি অনুমান করতে সক্ষম হয় না যে উত্স অনুসারে সূচককে ভ্রমণ করা ওয়াইএক্স (বা এমনকি কেবল অ্যানারি বিয়োগ এক্স) এর মতো একই ক্রমে সারিগুলি সরবরাহ করবে। পরিকল্পনার উভয় শাখা একটি বাছাই এড়াতে একটি সূচক ব্যবহার করে TOP 10তবে নীচের শাখায় এর পরে বাছাই করা হয়Diff (যদিও তারা ইতিমধ্যে সেই ক্রমে রয়েছে) একত্রিত হওয়ার জন্য পছন্দসই ক্রমে এগুলি পেতে।

অন্যান্য প্রশ্ন / সারণী সংজ্ঞাগুলির জন্য কেবল একটি শাখার এক প্রকারের সাথে একত্রীকরণ পরিকল্পনাটি পাওয়া সম্ভব বা জটিল নয় - কারণ এটি এসকিউএল সার্ভারের অর্ডারিং এক্সপ্রেশনটি খুঁজে পাওয়ার উপর নির্ভর করে:

  1. সূচক সন্ধানকারী নির্দিষ্ট অর্ডার সরবরাহ করবে তাই গ্রহণ করে তাই শীর্ষের আগে কোনও সাজানোর প্রয়োজন নেই ।
  2. মার্জ অপারেশনে ব্যবহার করে খুশি তাই এর পরে কোনও সাজানোর দরকার নেই requires TOP

1

আমি কিছুটা বিস্মিত এবং অবাক হয়েছি যে এই ক্ষেত্রে আমাদের ইউনিয়ন করতে হবে। নিম্নলিখিতটি সহজ এবং আরও কার্যকর

SELECT TOP (@top) *
FROM @YourTable
ORDER BY ABS(YourCol-@x)

নীচে উভয় প্রশ্নের তুলনা করে সম্পূর্ণ কোড এবং সম্পাদন পরিকল্পনা রয়েছে

DECLARE @YourTable TABLE (YourCol INT)
INSERT @YourTable (YourCol)
VALUES  (32),(11),(15),(123),(55),(54),(23),(43),(44),(44),(56),(23)

DECLARE @x INT = 100, @top INT = 5

--SELECT TOP 100 * FROM @YourTable
SELECT TOP (@top) *
FROM @YourTable
ORDER BY ABS(YourCol-@x)

;WITH CTE
     AS ((SELECT TOP 10 *
          FROM   @YourTable
          WHERE  YourCol > 32
          ORDER  BY YourCol ASC)
         UNION ALL
         (SELECT TOP 10 *
          FROM   @YourTable
          WHERE  YourCol <= 32
          ORDER  BY YourCol DESC))
SELECT TOP 10 *
FROM   CTE
ORDER  BY ABS(YourCol - 32) ASC 

কার্যকর করার পরিকল্পনার তুলনা


-3

মার্টিনের দ্বিতীয় পরামর্শটির সংশোধন:

WITH AB
     AS (SELECT *, ABS(32 - YourCol) AS Offset
         FROM   YourTable),
SELECT TOP 10 *
FROM   AB
ORDER  BY Offset ASC

2
এটি কিছুটা সহজ কোড হতে পারে তবে এটি আরও কম দক্ষ হতে চলেছে। আমরা SELECT TOP 10 * FROM YourTable ORDER BY ABS(YourCol - 32) ;এমনকি আরও সহজ ব্যবহার করতে পারে । দক্ষ না হয়।
ypercubeᵀᴹ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.