মাইএসকিউএলে ROW_NUMBER ()


281

এসকিউএল সার্ভারের ক্রিয়াকলাপটি প্রতিলিপি করার জন্য কি মাইএসকিউএলে একটি দুর্দান্ত উপায় আছে? ROW_NUMBER() ?

উদাহরণ স্বরূপ:

SELECT 
    col1, col2, 
    ROW_NUMBER() OVER (PARTITION BY col1, col2 ORDER BY col3 DESC) AS intRow
FROM Table1

তারপরে আমি উদাহরণস্বরূপ, প্রতিটি জোড়ের জন্য intRowসর্বোচ্চের সাথে একক সারি পেতে 1 এর সীমাবদ্ধ করার শর্ত যুক্ত করতে পারি ।col3(col1, col2)


9
greatest-n-per-groupআপনাকে অনুরূপ প্রশ্নের জন্য গাইড করতে ট্যাগ করা হয়েছে।
বিল কারভিন

1
সম্মিলিত ট্যাগ অনুসন্ধানেSql-Server এটি সর্বোচ্চ ভোট প্রাপ্ত আইটেম হিসাবে ট্যাগটি সরানো হয়েছে তবে এটি এসকিউএল সার্ভারের সাথে সত্যই প্রাসঙ্গিক নয়।
মার্টিন স্মিথ

একটি সাধারণ mysql সারি নম্বর ফাংশনের জন্য, datamakessense.com/mysql-rownum-row-number-function দেখুন
অ্যাড্রিয়ানআর

মাইএসকিউএলের জন্য, কেবলমাত্র কার্যকর সমাধানগুলি mysql.rjweb.org/doc.php/groupwise_max এ আলোচনা করা হয় । অনেকগুলি প্রচারিত সমাধানগুলির জন্য একটি পূর্ণ টেবিল স্ক্যান প্রয়োজন (বা আরও খারাপ)।
রিক জেমস

2
মাইএসকিউএলে বাস্তব বিশ্লেষণমূলক ফাংশন ROW_NUMBER, RANK, DESNSE_RANK এর জন্য নির্লজ্জভাবে স্ব প্রচারের সমাধান
কেনেথ জু

উত্তর:


102

আমি প্রতিটি (কল 1, কল 2) জোড়ার জন্য একক সর্বোচ্চ কল 3 দিয়ে সারিটি চাই।

এটি গ্রুপওয়ালা সর্বাধিক , সাধারণভাবে জিজ্ঞাসিত এসকিউএল প্রশ্নগুলির একটি (যেহেতু এটি সহজ হওয়া উচিত বলে মনে হয় তবে বাস্তবে এটি ধরণের নয়)।

আমি প্রায়শই নাল-স্ব-যোগদানের জন্য মোচড় দিয়ে থাকি:

SELECT t0.col3
FROM table AS t0
LEFT JOIN table AS t1 ON t0.col1=t1.col1 AND t0.col2=t1.col2 AND t1.col3>t0.col3
WHERE t1.col1 IS NULL;

"টেবিলের সারিগুলি পান যার জন্য কোল 1, কল 2 এর সাথে আর কোনও সারি মিলছে না, কল 2 এর উচ্চতর কল 3 নেই” " (আপনি এটি লক্ষ্য করুন এবং বেশিরভাগ অন্যান্য গ্রুপ-সলিউশন সলিউশন একাধিক সারি ফেরত দেবে যদি একাধিক সারিতে একই কোল 1, কল 2, কল 3 থাকে that's যদি সমস্যা হয় তবে আপনার পোস্ট-প্রসেসিংয়ের প্রয়োজন হতে পারে))


2
তবে কোন (কোল 1, কোল 2) জোড়ার জন্য কল 3 এর সর্বোচ্চ দুটি মান আছে? আপনি দুটি সারি দিয়ে শেষ করতে চাই।
পল

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

1
বোবিনস, সমাধানটি এখানে বরং জনপ্রিয় হয়ে ওঠে, তবে আমার একটি প্রশ্ন আছে। সমাধানটি মূলত একইরূপ যদি কেউ নিম্নলিখিত প্রশ্নের সাথে বৃহত্তম আইডি সন্ধান করার চেষ্টা করবে: একক সারিতে SELECT t1.id FROM test t1 LEFT JOIN test t2 ON t1.id>t2.id WHERE t2.id IS NULL;এটির জন্য কি n*n/2 + n/2তুলনা প্রয়োজন নয় ? আমি দেখতে পাচ্ছি না এমন কোনও অপ্টিমাইজেশন কি ঘটবে? আমি অনুরূপ প্রশ্নটি বিলকে অন্য থ্রেডে জিজ্ঞাসা করার চেষ্টা করেছি তবে মনে হয় তিনি এটিকে উপেক্ষা করেছেন।
newtover

2
@ পল - একসাথে একাধিক সারি রয়েছে যা এই গ্রুপে প্রতি সর্বাধিকের সাথে মেলে এবং আপনি কেবল একটি দখল করতে চান সেই ক্ষেত্রে মোকাবেলা করতে, আপনি টাইটি ভাঙতে সর্বদা ওএন ক্লজ লজিকের প্রাথমিক কী যুক্ত করতে পারেন ... t0.col3 থেকে সারণী নির্বাচন করুন AS t0 বাম যোগদানের টেবিল হিসাবে AS1 1 তে t0.col1 = t1.col1 এবং t0.col2 = t1.col2 এবং (t1.col3, t1.pk)> (t0.col3, t0.pk) যেখানে t1.col1 নাল;
জন আর্মস্ট্রং - এক্সজিসি

2
এটি আরও পঠনযোগ্য হবেSELECT t0.col3 FROM table AS t0 WHERE NOT EXISTS (select 1 from table AS t1 ON t0.col1=t1.col1 AND t0.col2=t1.col2 AND t1.col3>t0.col3)
wrschneider

204

মাইএসকিউএলে কোনও র‌্যাঙ্কিং কার্যকারিতা নেই। আপনি পেতে পারেন সবচেয়ে কাছের একটি ভেরিয়েবল ব্যবহার করা হয়:

SELECT t.*, 
       @rownum := @rownum + 1 AS rank
  FROM YOUR_TABLE t, 
       (SELECT @rownum := 0) r

সুতরাং কিভাবে আমার ক্ষেত্রে এটি কাজ করবে? আমার দুটি ভেরিয়েবলের দরকার, একটি কোল 1 এবং কোল 2 এর জন্য একটি? কল 1 পরিবর্তিত হলে কল 2 কোনওভাবে পুনরায় সেট করা দরকার ..?

হ্যাঁ. যদি এটি ওরাকল হয় তবে আপনি পরবর্তী মানটি শীর্ষে নেওয়ার জন্য নেতৃত্বের ফাংশনটি ব্যবহার করতে পারেন। ধন্যবাদ, ক্যাসনসুই আপনাকে মাইএসকিউএল প্রয়োগ করতে হবে তার জন্য যুক্তিটি coversেকে রাখে ।


1
হুম .... তাহলে আমার ক্ষেত্রে সেটা কীভাবে কাজ করবে? আমার দুটি ভেরিয়েবলের দরকার, একটি কোল 1 এবং কোল 2 এর জন্য একটি? কল 1 পরিবর্তিত হলে কল 2 কোনওভাবে পুনরায় সেট করা দরকার ..?
পল

ধন্যবাদ ... যেমন আমি উপরে বলেছি, এই উত্তরটি সমানভাবে গৃহীত বোবিন্সদের গ্রহণযোগ্য, তবে আমি কেবল একটিটিকে টিক দিতে পারি :-)
পল

9
একই বিবৃতিতে ব্যবহারকারী-সংজ্ঞায়িত ভেরিয়েবলগুলি অর্পণ এবং পড়া নির্ভরযোগ্য নয়। এটি এখানে নথিভুক্ত করা হয়েছে: dev.mysql.com/doc/refman/5.0/en/user-variables.html : "একটি সাধারণ নিয়ম হিসাবে আপনার কোনও ব্যবহারকারীর ভেরিয়েবলের জন্য কোনও মান নির্ধারণ করা উচিত নয় এবং একই বিবৃতিতে মানটি পড়া উচিত নয়। আপনি প্রত্যাশিত ফলাফল পেতে পারেন, তবে এটির গ্যারান্টিযুক্ত নয় user ব্যবহারকারী ভেরিয়েবলের সাথে জড়িত অভিব্যক্তিগুলির জন্য মূল্যায়নের ক্রমটি নির্ধারিত নয় এবং প্রদত্ত বিবৃতিতে থাকা উপাদানগুলির ভিত্তিতে পরিবর্তিত হতে পারে। "
রোল্যান্ড বোম্যান

1
@ রোল্যান্ড: আমি কেবলমাত্র ছোট ডেটাসেটে পরীক্ষা করেছি, কোনও সমস্যা হয়নি। খুব খারাপ মাইএসকিউএল এখনও কার্যকারিতা সম্বোধন করতে পারেনি - অনুরোধটি ২০০৮ সাল থেকে রয়েছে
ওএমজি পনিস

2
রোল্যান্ড নোট হিসাবে এটি অপরিজ্ঞাত আচরণ বলে মনে হচ্ছে। উদাহরণস্বরূপ এটি যে টেবিলে চেষ্টা করেছি তার পুরোপুরি ভুল ফলাফল দেয়:SELECT @row_num:=@row_num+1 AS row_number, t.id FROM (SELECT * FROM table1 WHERE col = 264 ORDER BY id) t, (SELECT @row_num:=0) var;
jbertman

81

আমি সর্বদা এই প্যাটার্ন অনুসরণ করে শেষ। এই টেবিল দেওয়া:

+------+------+
|    i |    j |
+------+------+
|    1 |   11 |
|    1 |   12 |
|    1 |   13 |
|    2 |   21 |
|    2 |   22 |
|    2 |   23 |
|    3 |   31 |
|    3 |   32 |
|    3 |   33 |
|    4 |   14 |
+------+------+

আপনি এই ফলাফল পেতে পারেন:

+------+------+------------+
|    i |    j | row_number |
+------+------+------------+
|    1 |   11 |          1 |
|    1 |   12 |          2 |
|    1 |   13 |          3 |
|    2 |   21 |          1 |
|    2 |   22 |          2 |
|    2 |   23 |          3 |
|    3 |   31 |          1 |
|    3 |   32 |          2 |
|    3 |   33 |          3 |
|    4 |   14 |          1 |
+------+------+------------+

এই ক্যোয়ারী চালিয়ে, যার কোনও পরিবর্তনশীল সংজ্ঞায়িত করার প্রয়োজন নেই:

SELECT a.i, a.j, count(*) as row_number FROM test a
JOIN test b ON a.i = b.i AND a.j >= b.j
GROUP BY a.i, a.j

আশা করি এইটি কাজ করবে!


1
কলামগুলি যদি মার্চচার বা চার হয় তবে কীভাবে আপনি এই কাঠামোর সাহায্যে পরিচালনা করতে পারেন?
তুষার

3
আপনি দুর্দান্ত, মোস্তি, আমি ঠিক এর জন্য সন্ধান করছি
ভাগ্যক্রিরিশ

সারি_সংখ্যার জন্য আপনার যুক্তি ব্যবহার করে এই উত্তরটি দিয়েছেন । ধন্যবাদ।
উত্সব

অপারেটার @Tushar <, >, <=, >=হাতল চর ও বর্ণানুক্রমিক অর্ডার VARCHAR ধরনের তথ্য; আমি আশা করি, ঠিক আপনি যা খুঁজছেন
অ্যালেক্স

1
@ আলমাজভিল্ডানভ আপনার এই ক্যোয়ারিকে কেবলমাত্র সাবকিউরি ফিল্টার হিসাবে ফিল্টার হিসাবে ব্যবহার করতে সক্ষম হবেন row_numbers <= 2 এবং এই উত্তরটির জন্য প্রচুর ধন্যবাদ মোস্টি , এটি নিখুঁত!
জ্যাক্স

61
SELECT 
    @i:=@i+1 AS iterator, 
    t.*
FROM 
    tablename AS t,
    (SELECT @i:=0) AS foo

1
প্রথমটি: = মনে হচ্ছে @ ওএমজি পনিগুলির উত্তর থেকে নিখোঁজ রয়েছে। এই পিটার জনসন পোস্ট করার জন্য ধন্যবাদ।
শোলসিংগার

আমার ধারণা (নির্বাচন করুন @ i: = 0) FooM বিবৃতিতে AS foo প্রথম টেবিল হওয়া উচিত, বিশেষত যদি অন্য টেবিলগুলি সাব-সিলেক্ট ব্যবহার করে
andig

আপনার এমনকি কেন '.. হিসাবে ফু' দরকার?
টম শিভারটন

@ টমচাইভারটন এটি অনুপস্থিত থাকলে, আপনি পাবেন: "ত্রুটি কোড: 1248 Every প্রতিটি
উত্সযুক্ত

1
এখানে র‌্যাঙ্ক অ্যাসাইনমেন্টটি সম্পূর্ণ
অপরিজ্ঞাত

27

এই নিবন্ধটি দেখুন, এটি মাইএসকিউএল দ্বারা পার্টিশনের সাথে এসকিউএল ROW_NUMBER () কীভাবে অনুকরণ করবেন তা দেখায়। আমি একটি ওয়ার্ডপ্রেস বাস্তবায়নের মধ্যে একই একই দৃশ্যে ছুটে এসেছি। আমার ROW_NUMBER () দরকার ছিল এবং এটি সেখানে ছিল না।

http://www.explodybits.com/2011/11/mysql-row-number/

নিবন্ধের উদাহরণটি ক্ষেত্র অনুসারে একটি একক বিভাজন ব্যবহার করছে। অতিরিক্ত ক্ষেত্রগুলি দ্বারা বিভাজন করতে আপনি এই জাতীয় কিছু করতে পারেন:

  SELECT  @row_num := IF(@prev_value=concat_ws('',t.col1,t.col2),@row_num+1,1) AS RowNumber
         ,t.col1 
         ,t.col2
         ,t.Col3
         ,t.col4
         ,@prev_value := concat_ws('',t.col1,t.col2)
    FROM table1 t,
         (SELECT @row_num := 1) x,
         (SELECT @prev_value := '') y
   ORDER BY t.col1,t.col2,t.col3,t.col4 

কনক্যাট_উজ ব্যবহার করে নালগুলি হ্যান্ডল হয়। আমি এটি কোন int, তারিখ এবং বার্চার ব্যবহার করে 3 টি ক্ষেত্রের বিপরীতে পরীক্ষা করেছি। আশাকরি এটা সাহায্য করবে. নিবন্ধটি পরীক্ষা করুন কারণ এটি এই ক্যোয়ারীটি ভেঙে দেয় এবং এটি ব্যাখ্যা করে।


1
অসাধারণ. এটি আসলে বিভাজন করে। খুব সহজ
স্টুয়ার্ট ওয়াট

1
স্ব-যোগদানের সাথে তুলনা করা, এটি অনেক বেশি দক্ষ, তবে যুক্তিটি নিয়ে একটি সমস্যা রয়েছে, সারি_নাম গণনা করার আগে ক্রম অবশ্যই ঘটবে, কনক্যাটও প্রয়োজনীয় নয়। `` @ @Row_num নির্বাচন করুন: = IF (@ prev_col1 = t.col1 এবং @ prev_col2 = t.col2), @ সারি_নাম + 1, 1) AS রো নাম্বার, t.col1, t.col2, t.col3, t.col4 , @ prev_col1: = t.col1, @ prev_col2: = t.col2 FROM (কোল 1, কল 2, কল 3 দ্বারা টেবিল 1 থেকে * নির্বাচন করুন) টি, (নির্বাচন করুন @ ক্রো_নাম: = 1, @ prev_col1: = '', @ prev_col2: = '') var `` `
কেনেথ Xu

আপনি Tu একটি subquery এই করা প্রয়োজন হয়, তাহলে তারপর যোগ limit 18446744073709551615বল করতে order byদফা।
xmedeko

concat_wsসঙ্গে খালি স্ট্রিং ''বিপজ্জনক: concat_ws('',12,3) = concat_ws('',1,23)। কিছু বিভাজক '_'ব্যবহার করা বা @ কেনেথ জু সমাধান ব্যবহার করা ভাল।
xmedeko


25

থেকে MySQL 8.0.0এবং উপরোক্ত আপনি নেটিভ বাতায়নযুক্ত ফাংশন ব্যবহার করতে পারেন।

1.4 মাইএসকিউএল 8.0 এ নতুন কী রয়েছে :

উইন্ডো ফাংশন।

মাইএসকিউএল এখন উইন্ডো ফাংশনগুলিকে সমর্থন করে যা কোয়েরি থেকে প্রতিটি সারির জন্য, সেই সারি সম্পর্কিত সারি ব্যবহার করে একটি গণনা সম্পাদন করে। এর মধ্যে RANK (), LAG (), এবং NTILE () এর মতো ফাংশন অন্তর্ভুক্ত রয়েছে। এছাড়াও, বেশ কয়েকটি বিদ্যমান সামগ্রিক ফাংশন এখন উইন্ডো ফাংশন হিসাবে ব্যবহার করা যেতে পারে; উদাহরণস্বরূপ, এসইউএম () এবং এভিজি ()।

ROW_NUMBER () ওভার_ ক্লাউজ :

এটির পার্টিশনের মধ্যে বর্তমান সারিটির সংখ্যা প্রদান করে। সারি সংখ্যাগুলি 1 থেকে বিভাজন সারিগুলির সংখ্যা পর্যন্ত বিস্তৃত।

অর্ডার বাই অর্ডারে ক্রমগুলিতে সংখ্যা নির্ধারণ করা হয়। অর্ডার দ্বারা না করে, সারি সংখ্যা নির্ধারিত।

ডেমো:

CREATE TABLE Table1(
  id INT AUTO_INCREMENT PRIMARY KEY, col1 INT,col2 INT, col3 TEXT);

INSERT INTO Table1(col1, col2, col3)
VALUES (1,1,'a'),(1,1,'b'),(1,1,'c'),
       (2,1,'x'),(2,1,'y'),(2,2,'z');

SELECT 
    col1, col2,col3,
    ROW_NUMBER() OVER (PARTITION BY col1, col2 ORDER BY col3 DESC) AS intRow
FROM Table1;

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


1
দীর্ঘশ্বাস ... শেষ অবধি!
ব্যবহৃত_বাই_আলডিয়ার

15

আমি মোস্টি মোস্তোচোর সমাধানটির জন্য তার প্রশ্নের কোডটিতে সামান্য পরিবর্তন করেও ভোট দেব:

SELECT a.i, a.j, (
    SELECT count(*) from test b where a.j >= b.j AND a.i = b.i
) AS row_number FROM test a

যা একই ফলাফল দেবে:

+------+------+------------+
|    i |    j | row_number |
+------+------+------------+
|    1 |   11 |          1 |
|    1 |   12 |          2 |
|    1 |   13 |          3 |
|    2 |   21 |          1 |
|    2 |   22 |          2 |
|    2 |   23 |          3 |
|    3 |   31 |          1 |
|    3 |   32 |          2 |
|    3 |   33 |          3 |
|    4 |   14 |          1 |
+------+------+------------+

টেবিলের জন্য:

+------+------+
|    i |    j |
+------+------+
|    1 |   11 |
|    1 |   12 |
|    1 |   13 |
|    2 |   21 |
|    2 |   22 |
|    2 |   23 |
|    3 |   31 |
|    3 |   32 |
|    3 |   33 |
|    4 |   14 |
+------+------+

কোয়েরিটি কেবলমাত্র নেস্টেট সিলেক্টের উপর নির্ভর করে জোইন এবং গ্রুপ ব্যবহার করে না এমন একমাত্র পার্থক্যের সাথে।


এটি কি আরও ভাল হওয়ার কথা? তারা উভয়ই
চতুষ্কোণ

প্রকৃতপক্ষে, নেস্টেড সিলেকশনগুলি মাইএসকিউএল-তে খুব ভাল to আমার ধারণা, উপরের পরিবর্তনশীল-ভিত্তিক উদাহরণগুলি বেশিরভাগ ব্যবহারিক ক্ষেত্রে ভাল কাজ করে।
abcdn

1
পরিবর্তনশীল ভিত্তিক কোনও উত্তর আসলে সংজ্ঞায়িত আচরণ ব্যবহার করছে তা আমি নিশ্চিত নই ...
jbertman

আমি দুঃখিত, আমি নিশ্চিত নই যে আপনি "সংজ্ঞায়িত আচরণ" দ্বারা বোঝাতে চেয়েছিলেন got আপনার অর্থ কি এটি আপনার পক্ষে কাজ করে না, বা আপনি কেবল উদ্বিগ্ন যে এটি নথিভুক্ত নয়?
abcdn

1
"অপরিজ্ঞাত আচরণ" এর অর্থ হ'ল এটি কাজ করার জন্য নথিভুক্ত নয় এবং / অথবা কাজের নিশ্চয়তা না পাওয়ার জন্য নথিভুক্ত। এই পৃষ্ঠায় মন্তব্যগুলিতে ডকুমেন্টেশন উদ্ধৃতি এবং লিঙ্কগুলি দেখুন। এটি যা প্রত্যাবর্তন করতে পারে (অনুভূতভাবে) যা চায় / অনুমান করে / অনুমান করে / কল্পনা করে। বাস্তবায়নের কয়েকটি সংস্করণের জন্য সিএএসই ইনক্রিমেন্টিং এবং ভেরিয়েবলগুলি ব্যবহার করে নির্দিষ্ট ক্যোয়ারী এক্সপ্রেশনগুলি কোডটি দেখে পারকোনায় প্রোগ্রামারদের দ্বারা কাজ করার জন্য দেখানো হয়েছে। যে কোনও রিলিজের সাথে এটি পরিবর্তন হতে পারে।
ফিলিপ্সি

12

আমি একটি ফাংশন সংজ্ঞায়িত করব:

delimiter $$
DROP FUNCTION IF EXISTS `getFakeId`$$
CREATE FUNCTION `getFakeId`() RETURNS int(11)
    DETERMINISTIC
begin
return if(@fakeId, @fakeId:=@fakeId+1, @fakeId:=1);
end$$

তাহলে আমি করতে পারি:

select getFakeId() as id, t.* from table t, (select @fakeId:=0) as t2;

এখন আপনার কাছে সাব-কোয়েরি নেই, যা আপনার দৃষ্টিতে থাকতে পারে না।


একটি সীমাবদ্ধতা নিয়ে কাজ করে: আপনি যদি কোয়েরিটি বেশ কয়েকবার সম্পাদন করেন, আপনি একই ফলস্বরূপ সেটটির জন্য ক্রমবর্ধমান জাল আইডিস পাবেন
স্টিফান রিখটার

আপনি @ fakeId = 0 সেট পাঠাতে পারেন; প্রতিবার আপনি কোয়েরিটি চালাতে চান, অনুকূল নয় তবে কাজ করে
jmpeace

আপনি ডিটারমিনিস্টিক সরিয়ে দিলে সত্যিই একটি বিজোড় সমস্যা ঘটে। এরপরে অর্ডার ব্যবহার করার সময় নকলআইডিটি ভুল। কেন?
ক্রিস Muench

8

mysql এ সারি_সংখ্যার জন্য ক্যোয়ারী

set @row_number=0;
select (@row_number := @row_number +1) as num,id,name from sbs

এটি আপডেটের ক্যোয়ারিতে ব্যবহার করা যেতে পারে? আমি চেষ্টা করছি তবে আমি একটি "কলামের জন্য ডেটা কাটা ..." ত্রুটি পেয়েছি।
দিয়েগো 21

1
যদি কেউ আপডেটে এটিকে ব্যবহার করতে আগ্রহী হয় তবে এটি কাজ করতে অবশ্যই এটি একটি সাব-কোয়েরি হিসাবে ব্যবহার করা উচিত। আপডেট করুন <টেবিল> সেট <ক্ষেত্র> = (নির্বাচন করুন row @ আরো_ নাম্বার: = \ @ আরো_ নাম্বার +1) অর্ডার <আপনার অর্ডার কলাম>> দ্বারা; অর্ডার কলামটি সারিগুলির মান ক্রম নির্ধারণ করে।
দিয়েগো


4

যে সমাধানটি আমি সর্বোত্তমভাবে কাজ করেছিলাম তা হ'ল এই জাতীয় উপকরণটি ব্যবহার করা:

SELECT 
    col1, col2, 
    (
        SELECT COUNT(*) 
        FROM Table1
        WHERE col1 = t1.col1
        AND col2 = t1.col2
        AND col3 > t1.col3
    ) AS intRow
FROM Table1 t1

পার্টিশন বাই কলামগুলি কেবল '=' এর সাথে তুলনা করে এবং এন্ড দ্বারা পৃথক করা হয়। অর্ডার বাই কলামগুলিকে '<' বা '>' এর সাথে তুলনা করা হবে এবং ওআর দ্বারা পৃথক করা হবে।

আমি এটি সামান্য ব্যয়বহুল হলেও, এটি খুব নমনীয় বলে মনে করেছি।


4

রাউনবার কার্যকারিতা নকল করা যায় না। আপনি প্রত্যাশিত ফলাফলগুলি পেতে পারেন তবে আপনি সম্ভবত কিছু পর্যায়ে হতাশ হবেন। এখানে মাইএসকিএল ডকুমেন্টেশন যা বলে:

অন্যান্য বিবৃতিগুলির জন্য, যেমন নির্বাচন করুন, আপনি প্রত্যাশিত ফলাফলগুলি পেতে পারেন, তবে এটির নিশ্চয়তা নেই। নিম্নলিখিত বিবৃতিতে, আপনি ভাবতে পারেন যে মাইএসকিউএল প্রথমে @a কে মূল্যায়ন করবে এবং তারপরে একটি অ্যাসাইনমেন্ট দ্বিতীয়টি করবে: নির্বাচন করুন @ এ, @ এ: = @ এ + 1, ...; তবে, ব্যবহারকারী ভেরিয়েবল জড়িত এক্সপ্রেশন জন্য মূল্যায়নের ক্রম নির্ধারিত হয়।

শুভেচ্ছা, জর্জি।


আমি অনুসরণ করি না "@I: = @ i + 1 পজিশন হিসাবে" কীভাবে "ROW_NUMBER () ওভারের (যোগফল (স্কোর) ডেস্ক) পজিশনে অর্ডার করবেন" এর প্রত্যক্ষ প্রতিস্থাপন নয়?
টম শিভারটন

1
@ টমচিভারটন কারণ ম্যানুয়ালটি ঠিক আছে বলে এটির আচরণ সংজ্ঞাযুক্ত নয়।
ফিলিপ্সি

4

মারিয়াডিবি 10.2 "উইন্ডো ফাংশনগুলি" বাস্তবায়ন করছে, যার মধ্যে রয়েছে র্যাঙ্ক (), ROW_NUMBER () এবং আরও কয়েকটি বিষয়:

https://mariadb.com/kb/en/mariadb/window-functions/

এই মাসে পারকোনা লাইভের একটি আলাপের ভিত্তিতে, তারা যুক্তিসঙ্গতভাবে ভাল আশাবাদী।

সিনট্যাক্সটি প্রশ্নের কোডের মতো।


2

"পার্টিশন বাই" অংশটি কভার করার কোনও সহজ উত্তর আমি দেখতে পাচ্ছি না তাই এখানে আমার:

SELECT
    *
FROM (
    select
        CASE WHEN @partitionBy_1 = l THEN @row_number:=@row_number+1 ELSE @row_number:=1 END AS i
        , @partitionBy_1:=l AS p
        , t.*
    from (
        select @row_number:=0,@partitionBy_1:=null
    ) as x
    cross join (
        select 1 as n, 'a' as l
        union all
        select 1 as n, 'b' as l    
        union all
        select 2 as n, 'b' as l    
        union all
        select 2 as n, 'a' as l
        union all
        select 3 as n, 'a' as l    
        union all    
        select 3 as n, 'b' as l    
    ) as t
    ORDER BY l, n
) AS X
where i > 1
  • অর্ডার বাই ক্লজটি অবশ্যই আপনার ROW_NUMBER প্রয়োজন প্রতিফলিত করবে। সুতরাং ইতিমধ্যে একটি স্পষ্ট সীমাবদ্ধতা রয়েছে: আপনার একই সময়ে এই ফর্মের বেশ কয়েকটি ROW_NUMBER "এমুলেশন" থাকতে পারে না।
  • "গণিত কলাম" এর ক্রমটি গুরুত্বপূর্ণ । আপনার যদি মাইএসকিএল থেকে অন্য ক্রমে সেই কলামগুলি গণনা করা হয় তবে এটি কার্যকর নাও হতে পারে।
  • এই সাধারণ উদাহরণে আমি কেবল একটি রেখেছি তবে আপনার বেশ কয়েকটি "পার্টির বাই বাই" অংশ থাকতে পারে

        CASE WHEN @partitionBy_1 = part1 AND @partitionBy_2 = part2 [...] THEN @row_number:=@row_number+1 ELSE @row_number:=1 END AS i
        , @partitionBy_1:=part1 AS P1
        , @partitionBy_2:=part2 AS P2
        [...] 
    FROM (
        SELECT @row_number:=0,@partitionBy_1:=null,@partitionBy_2:=null[...]
    ) as x

1

কিছুটা দেরি হলেও উত্তরগুলির সন্ধানকারী কাউকে সহায়তাও করতে পারে ...

সারি / সারি_সংখ্যার উদাহরণের মধ্যে - পুনরাবৃত্ত ক্যোয়ারী যা কোনও এসকিউএল ব্যবহৃত হতে পারে:

WITH data(row_num, some_val) AS 
(
 SELECT 1 row_num, 1 some_val FROM any_table --dual in Oracle
  UNION ALL
 SELECT row_num+1, some_val+row_num FROM data WHERE row_num < 20 -- any number
)
SELECT * FROM data
 WHERE row_num BETWEEN 5 AND 10
/

ROW_NUM    SOME_VAL
-------------------
5           11
6           16
7           22
8           29
9           37
10          46

2
দুঃখিত তবে যতদূর আমি জানি মাইএসকিউএল সাধারণ টেবিল এক্সপ্রেশন সমর্থন করে না ।
vালভারো গঞ্জালেজ

এটি এখনই করে ... @ vlvaroGonzález মাইএসকিউএল 8 কেবলমাত্র সিটিই এবং উইন্ডো ফাংশন সমর্থন করে, তাই এই উত্তরটি পুরানো মাইএসকিউএল সংস্করণগুলিতে ব্যবহার করা সত্যিকার অর্থে আসে না ..
রায়মন্ড নিজল্যান্ড

1

এটি মাইএসকিউএল-এ ROW_NUMBER () এবং পার্টিশন সরবরাহ করে এমন একই কার্যকারিতাটির অনুমতি দেয়

SELECT  @row_num := IF(@prev_value=GENDER,@row_num+1,1) AS RowNumber
       FirstName, 
       Age,
       Gender,
       @prev_value := GENDER
  FROM Person,
      (SELECT @row_num := 1) x,
      (SELECT @prev_value := '') y
  ORDER BY Gender, Age DESC

1

কিছুটা দেরি হলেও আজ আমার একই প্রয়োজন ছিল তাই আমি গুগলে অনুসন্ধান করেছি এবং শেষ পর্যন্ত পিনাল ডেভের নিবন্ধে একটি সাধারণ সাধারণ পদ্ধতির সন্ধান পেয়েছি http://blog.sqlauthority.com/2014/03/09/mysql-reset-row -number-জন্য-প্রতিটি-গ্রুপ-পার্টিশন-বাই-সারি-নম্বর /

আমি পলের মূল প্রশ্নটির দিকে ফোকাস করতে চেয়েছিলাম (এটি আমার সমস্যাও ছিল) তাই আমি আমার সমাধানটি একটি কার্যকরী উদাহরণ হিসাবে সংক্ষিপ্ত করে বলি।

বীচুস আমরা দুটি কলামের উপর বিভাজন করতে চাই আমি একটি নতুন গ্রুপ শুরু হয়েছিল কিনা তা সনাক্ত করতে পুনরাবৃত্তির সময় একটি এসইটি ভেরিয়েবল তৈরি করব।

SELECT col1, col2, col3 FROM (
  SELECT col1, col2, col3,
         @n := CASE WHEN @v = MAKE_SET(3, col1, col2)
                    THEN @n + 1 -- if we are in the same group
                    ELSE 1 -- next group starts so we reset the counter
                END AS row_number,
         @v := MAKE_SET(3, col1, col2) -- we store the current value for next iteration
    FROM Table1, (SELECT @n := 0, @v := NULL) r -- helper table for iteration with startup values
   ORDER BY col1, col2, col3 DESC -- because we want the row with maximum value
) x WHERE row_number = 1 -- and here we select exactly the wanted row from each group

3 টি MAKE_SET এর প্রথম প্যারামিটারে যা আমি SET (3 = 1 | 2) তে উভয়ই মান চাই। অবশ্যই গ্রুপগুলি তৈরির ক্ষেত্রে যদি দুটি বা তার বেশি কলাম না থাকে তবে আমরা MAKE_SET অপারেশনটি শেষ করতে পারি। নির্মাণও ঠিক একই রকম। এটি আমার জন্য প্রয়োজনীয় হিসাবে কাজ করছে। পিনাল ডেভকে তার সুস্পষ্ট বিক্ষোভের জন্য অনেক ধন্যবাদ।


1
নোট করুন যে ORDER BYএকটি উপকণ্ঠে উপেক্ষা করা যেতে পারে (দেখুন mariadb.com/kb/en/mariadb/… )। এর প্রস্তাবিত সমাধান হ'ল LIMIT 18446744073709551615সাবকিউরিতে যুক্ত করা, যা এক ধরণের বাধ্যতামূলক করে। তবে এটি পারফরম্যান্স সমস্যার কারণ হতে পারে এবং বিশাল টেবিলগুলি সত্যই
প্রকাশের

1

এটি একটি সমাধান হতে পারে:

SET @row_number = 0;

SELECT 
    (@row_number:=@row_number + 1) AS num, firstName, lastName
FROM
    employees

যদিও এটি কোনও বিভাজন করে না, এবং এটি একটি উচ্চ উদ্ধৃত উত্তরের তুলনায় উল্লেখযোগ্যভাবে আলাদা নয়
Caius Jard

1

মাইএসকিউএল ROW_NUMBER () সমর্থন করে সংস্করণ থেকে 8.0+

আপনি যদি মাইএসকিউএল 8.0 বা তার পরে ব্যবহার করেন তবে এটি ROW_NUMBER () ফাংশনটি পরীক্ষা করে দেখুন। অন্যথায়, আপনি ROW_NUMBER () ফাংশন অনুকরণ করেছেন।

সারি_নম্বার () একটি র‌্যাঙ্কিং ফাংশন যা প্রথম সারির 1 থেকে শুরু করে একটি সারির ক্রমিক সংখ্যা দেয়।

পুরানো সংস্করণের জন্য,

SELECT t.*, 
       @rowid := @rowid + 1 AS ROWID
  FROM TABLE t, 
       (SELECT @rowid := 0) dummy;

1

গুরুত্বপূর্ণ: দয়া করে মাইএসকিউএল 8+ এ আপগ্রেড করার কথা বিবেচনা করুন এবং সংজ্ঞায়িত এবং ডকুমেন্টেড ROW_NUMBER () ফাংশনটি ব্যবহার করুন এবং মাইএসকিউএল-র বৈশিষ্ট্য সীমিত প্রাচীন সংস্করণে আবদ্ধ পুরানো হ্যাকগুলি খনন করুন

এখন এই হ্যাকগুলির মধ্যে একটি:

এখানে যে উত্তরগুলি ইন-কোয়েরি ভেরিয়েবলগুলি ব্যবহার করে / বেশিরভাগই ডকুমেন্টেশন বলে (প্যারাফ্রেজ) বলে তা উপেক্ষা করে বলে মনে হচ্ছে:

উপরে থেকে নীচে ক্রমে মূল্যায়ন করা হচ্ছে SELECT তালিকার আইটেমগুলির উপর নির্ভর করবেন না। একটি নির্বাচন আইটেমে ভেরিয়েবল বরাদ্দ করবেন না এবং অন্য একটিতে সেগুলি ব্যবহার করবেন না

এই হিসাবে, তাদের একটি ভুল ঝুঁকি রয়েছে যে তারা ভুল উত্তরটি ছড়িয়ে দেবে, কারণ তারা সাধারণত একটি করে

select
  (row number variable that uses partition variable),
  (assign partition variable)

এগুলি যদি নীচে আপকে মূল্যায়ন করা হয় তবে সারি নম্বর কাজ করা বন্ধ করবে (কোনও পার্টিশন নেই)

সুতরাং আমাদের কার্যকর গ্যারান্টিযুক্ত আদেশ সহ কিছু ব্যবহার করতে হবে। পরিস্থিতি যখন প্রবেশ করুন:

SELECT
  t.*, 
  @r := CASE 
    WHEN col = @prevcol THEN @r + 1 
    WHEN (@prevcol := col) = null THEN null
    ELSE 1 END AS rn
FROM
  t, 
  (SELECT @r := 0, @prevcol := null) x
ORDER BY col

বাহ্যরেখা এলডি হিসাবে, প্রডকোলের কার্যক্রমের ক্রমটি গুরুত্বপূর্ণ - প্রব্যাকলকে বর্তমান সারিটির একটি মান নির্ধারণের পূর্বে বর্তমান সারির মানটির সাথে তুলনা করতে হবে (অন্যথায় এটি বর্তমান সারিগুলির করল মান হবে, পূর্ববর্তী সারির কোলের মান নয়) ।

এটি কীভাবে একসাথে ফিট হয় তা এখানে:

  • প্রথম WHEN মূল্যায়ন করা হয়। যদি এই সারির কর্নটি আগের সারির কর্নের মতো হয় তবে @ আর বাড়ানো হয় এবং CASE থেকে ফিরে আসে। এই রিটার্নের নেতৃত্বাধীন মানগুলিতে @ আরআর সংরক্ষণ করা হয়। এটি মাইএসকিউএল এর একটি বৈশিষ্ট্য যা অ্যাসাইনমেন্টটি ফলাফলকে সারিগুলিতে @ আর এর মধ্যে যা বরাদ্দ করা হয়েছে তার নতুন মান প্রদান করে।

  • ফলাফলের সেটটিতে প্রথম সারির জন্য, @ প্রিভকোলটি নাল (এটি সাবকোয়ারিতে নাল থেকে শুরু করা হয়েছে) সুতরাং এই ভবিষ্যদ্বাণীটি মিথ্যা। এই প্রথম শিকারী প্রতি বার কর্ন পরিবর্তন হওয়ার সাথেও মিথ্যা ফেরত দেয় (বর্তমান সারিটি আগের সারির চেয়ে পৃথক)। এটি দ্বিতীয় WHEN মূল্যায়নের কারণ হয়।

  • দ্বিতীয় WHEN এর পূর্বাভাস সর্বদা মিথ্যা এবং @Prevcol এ একটি নতুন মান নির্ধারণের জন্য এটি বিশুদ্ধরূপে বিদ্যমান। কারণ এই সারির কর্নটি আগের সারির কর্নের থেকে আলাদা (আমরা এটি জানি কারণ এটি যদি একই থাকে তবে প্রথম WHEN ব্যবহার করা হত), পরের বারের পরীক্ষার জন্য আমাদের নতুন মান নির্ধারণ করতে হবে। যেহেতু অ্যাসাইনমেন্টটি করা হয় এবং তারপরে অ্যাসাইনমেন্টের ফলাফলটি নলের সাথে তুলনা করা হয়, এবং নলের সাথে সমান যে কোনও কিছু মিথ্যা, এই শিকারী সর্বদা মিথ্যা। তবে কমপক্ষে এটির মূল্যায়ন করা এই সারিটি থেকে কর্নেলের মান রাখার কাজ করেছে, সুতরাং এটি পরবর্তী সারির কর্নমূল্যের তুলনায় মূল্যায়ন করা যেতে পারে

  • দ্বিতীয় WHEN টি মিথ্যা বলে এর অর্থ এমন পরিস্থিতিতে রয়েছে যেখানে আমরা (কল) দিয়ে বিভাজন করছি কলামটি পরিবর্তিত হয়েছে, এটি ELSE যা @r এর জন্য একটি নতুন মান দেয়, 1 থেকে নম্বরটি পুনরায় আরম্ভ করে

আমরা এটি এমন পরিস্থিতিতে পৌঁছেছি যেখানে এটি:

SELECT
  t.*, 
  ROW_NUMBER() OVER(PARTITION BY pcol1, pcol2, ... pcolX ORDER BY ocol1, ocol2, ... ocolX) rn
FROM
  t

সাধারণ ফর্ম আছে:

SELECT
  t.*, 
  @r := CASE 
    WHEN col1 = @pcol1 AND col2 = @pcol2 AND ... AND colX = @pcolX THEN @r + 1 
    WHEN (@pcol1 := pcol1) = null OR (@pcol2 := col2) = null OR ... OR (@pcolX := colX) = null THEN null
    ELSE 1 
  END AS rn
FROM
  t, 
  (SELECT @r := 0, @pcol1 := null, @pcol2 := null, ..., @pcolX := null) x
ORDER BY pcol1, pcol2, ..., pcolX, ocol1, ocol2, ..., ocolX

পাদটিকা:

  • পি-সি-পি-এর অর্থ "পার্টিশন", ওকোলে ও-র অর্থ "অর্ডার" - সাধারণ আকারে আমি ভিজ্যুয়াল ক্লাটারকে হ্রাস করতে ভেরিয়েবল নাম থেকে "পূর্ব" বাদ দিলাম

  • চারপাশে বন্ধনী (@pcolX := colX) = nullগুরুত্বপূর্ণ। এগুলি ছাড়াই আপনি @pcolX এ নাল বরাদ্দ করবেন এবং জিনিসগুলি কাজ করা বন্ধ করবে

  • এটি একটি সমঝোতা যে ফলাফল সেটটি পূর্ববর্তী কলামটির তুলনায় কাজ করার জন্য পার্টিশন কলামগুলিও অর্ডার করতে হবে। আপনি এইভাবে আপনার রনবার্টটিকে একটি কলাম অনুসারে অর্ডার করতে পারবেন না তবে আপনার ফলাফল সেটটি অন্যটিকে আদেশ করা হয়েছে আপনি এটিকে সাবকিউয়ের সাথে সমাধান করতে সক্ষম হতে পারেন তবে আমি বিশ্বাস করি যে ডকুমেন্টগুলি আরও বলে যে লিমিটেড ব্যবহার না করা হলে সাব-কোয়ের অর্ডার অগ্রাহ্য করা যেতে পারে এবং এটি প্রভাব ফেলতে পারে কর্মক্ষমতা

  • পদ্ধতিটি কাজ করে যাচাই করার বাইরে আমি এগুলিতে প্রবেশ করি নি, তবে দ্বিতীয় ঝুঁকির মধ্যে যদি ভবিষ্যদ্বাণী করা হয় তবে অপটিমাইজ করা হবে (নাল তুলনায় যে কোনও কিছুই নাল / মিথ্যা তাই অ্যাসাইনমেন্ট চালানো কেন বিরক্ত করবে) এবং মৃত্যুদন্ড কার্যকর করা হবে না , এটিও থামে। আমার অভিজ্ঞতায় এটি ঘটবে বলে মনে হচ্ছে না তবে আমি আনন্দের সাথে মন্তব্যগুলি গ্রহণ করব এবং যদি যুক্তিসঙ্গতভাবে ঘটতে পারে তবে সমাধানের প্রস্তাব দেব

  • @PcolX ভেরিয়েবলগুলি তৈরি করে এমন সাব-কোয়রিতে আপনার কলামগুলির প্রকৃত প্রকারগুলিতে @pcolX তৈরি করা নালগুলি নিক্ষেপ করা বুদ্ধিমানের কাজ হতে পারে: select @pcol1 := CAST(null as INT), @pcol2 := CAST(null as DATE)


এর কোন যৌক্তিকতা নেই। ঠিক একই পরিবর্তনশীল থেকে অ্যাসাইন করা ও পড়ার মতো অন্যান্য উত্তরগুলির মতো।
ফিলিপ্সি

আপনি কি আরও বিস্তারিত ফিল সরবরাহ করতে পারবেন?
কায়ুস জার্ড

এই পৃষ্ঠায় আমার অন্যান্য মন্তব্য দেখুন। গুগলিংয়ের সাইট: স্ট্যাকওভারফ্লো ডটকম "ফিলিপ্সি" মাইএসকিএল ভেরিয়েবল (সেট করুন বা এসাইনমেন্ট অর্পণ করুন বা লিখুন) পড়ুন ': আমার একটি উত্তর এবং একটি বাগ রিপোর্ট আমার এই মন্তব্যে একটি মন্তব্যে লিঙ্ক করেছে যেখানে স্বীকৃত উত্তরটি সাথে সাথে ম্যানুয়ালটি অবিলম্বে উদ্ধৃত করে দাবীতে এটি এর বিরোধী কিছু করা ঠিক আছে। ম্যানুয়াল রি ভেরিয়েবলগুলি পড়ুন এবং পুনরায় নিয়োগ করুন।
ফিলিপ্সি


আমি আপনার উদ্বেগ বুঝতে পারি
Caius Jard

0

এটি সর্বাধিক শক্তিশালী সমাধান নয় - তবে আপনি যদি কেবল কয়েকটি পৃথক মান সহ কোনও ক্ষেত্রের মধ্যে বিভাজনযুক্ত র‌্যাঙ্ক তৈরি করতে সন্ধান করছেন তবে আপনার প্রয়োজনীয় যতগুলি ভেরিয়েবল যুক্ত রয়েছে তার সাথে যুক্তি কিছু ক্ষেত্রে ব্যবহার করা উচিত নয়।

এর আগে কিছু আমার জন্য কাজ করেছে:

SELECT t.*, 
   CASE WHEN <partition_field> = @rownum1 := @rownum1 + 1 
     WHEN <partition_field> = @rownum2 := @rownum2 + 1 
     ...
     END AS rank
FROM YOUR_TABLE t, 
   (SELECT @rownum1 := 0) r1, (SELECT @rownum2 := 0) r2
ORDER BY <rank_order_by_field>
;

আশা করি যে অর্থে / সহায়তা করে!


-1

যখন আমাদের একাধিক কলাম থাকবে তখন RowNumber তৈরি করার জন্য আমার পক্ষে এটি পুরোপুরি কাজ করে। এই ক্ষেত্রে দুটি কলাম।

SELECT @row_num := IF(@prev_value= concat(`Fk_Business_Unit_Code`,`NetIQ_Job_Code`), @row_num+1, 1) AS RowNumber, 
    `Fk_Business_Unit_Code`,   
    `NetIQ_Job_Code`,  
    `Supervisor_Name`,  
    @prev_value := concat(`Fk_Business_Unit_Code`,`NetIQ_Job_Code`)  
FROM (SELECT DISTINCT `Fk_Business_Unit_Code`,`NetIQ_Job_Code`,`Supervisor_Name`         
      FROM Employee    
      ORDER BY `Fk_Business_Unit_Code`, `NetIQ_Job_Code`, `Supervisor_Name` DESC) z,  
(SELECT @row_num := 1) x,  
(SELECT @prev_value := '') y  
ORDER BY `Fk_Business_Unit_Code`, `NetIQ_Job_Code`,`Supervisor_Name` DESC

-3
set @i = 1;  
INSERT INTO ARG_VALUE_LOOKUP(ARG_VALUE_LOOKUP_ID,ARGUMENT_NAME,VALUE,DESCRIPTION,UPDATE_TIMESTAMP,UPDATE_USER,VER_NBR,OBJ_ID) 
select @i:= @i+1 as ARG_VALUE_LOOKUP_ID,ARGUMENT_NAME,VALUE,DESCRIPTION,CURRENT_TIMESTAMP,'admin',1,UUID() 
FROM TEMP_ARG_VALUE_LOOKUP 
order by ARGUMENT_NAME;

1
দয়া করে কোনও উত্তর ফর্ম্যাট করার চেষ্টা করুন এবং আপনি যা করার চেষ্টা করছেন সে সম্পর্কে কিছু অতিরিক্ত প্রসঙ্গ দিন। এই মুহুর্তে এটি খারাপভাবে বিন্যাসিত পাঠ্য ছাড়া আর কিছুই নয়।
ইয়ানিক মিউস

2
এটির মূল প্রশ্নের সাথে কোনও সম্পর্ক আছে বলে মনে হয় না। যদি আপনার নিজের কোনও প্রশ্ন থাকে তবে দয়া করে এটি আলাদাভাবে জিজ্ঞাসা করুন।
জেরোইন মোস্টার্ট

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