এখন যে মাইএসকিউএল 8.0 পুনরাবৃত্ত অনুসন্ধানগুলি সমর্থন করে , আমরা বলতে পারি যে সমস্ত জনপ্রিয় এসকিউএল ডাটাবেসগুলি স্ট্যান্ডার্ড সিনট্যাক্সে পুনরাবৃত্ত অনুসন্ধানগুলি সমর্থন করে ।
WITH RECURSIVE MyTree AS (
SELECT * FROM MyTable WHERE ParentId IS NULL
UNION ALL
SELECT m.* FROM MyTABLE AS m JOIN MyTree AS t ON m.ParentId = t.Id
)
SELECT * FROM MyTree;
আমি আমার উপস্থাপনায় মাইএসকিউএল 8.0 এ পুনরাবৃত্ত অনুসন্ধানগুলি পরীক্ষা করেছি 2017 সালে রিকার্সিভ কোয়েরি থ্রোডাউন ।
নীচে আমার মূল উত্তরটি ২০০৮ সাল থেকে:
রিলেশনাল ডাটাবেসে গাছ-কাঠামোগত ডেটা সংরক্ষণ করার বিভিন্ন উপায় রয়েছে। আপনি আপনার উদাহরণে যা দেখান তা দুটি পদ্ধতি ব্যবহার করে:
- সংলগ্ন তালিকা ("পিতামাতার" কলাম) এবং
- পাথ গণনা (আপনার নাম কলামে বিন্দুযুক্ত সংখ্যা)।
অন্য সমাধানটিকে নেস্টেড সেটস বলা হয় এবং এটি একই টেবিলেও সংরক্ষণ করা যায়। এই নকশাগুলির বিষয়ে আরও অনেক তথ্যের জন্য জো সেলকো রচিত " এসকিউএল এর জন্য এসকিউএল এ গাছ এবং হায়ারারচিগুলি " পড়ুন ।
গাছের কাঠামোগত ডেটা সংরক্ষণ করার জন্য আমি সাধারণত ক্লোজার টেবিল (ওরফে "অ্যাডজেসেন্সি রিলেশন") নামে একটি ডিজাইন পছন্দ করি । এটির জন্য অন্য টেবিলের প্রয়োজন, তবে গাছগুলি জিজ্ঞাসা করা খুব সহজ।
আমি এসকিউএল এবং পিএইচপি এবং আমার বই এসকিউএল অ্যান্টিপ্যাটার্নস: হিজরাইজিকাল ডেটাগুলির মডেলগুলির জন্য আমার উপস্থাপনায় ক্লোজার টেবিলটি কভার করি : ডেটাবেস প্রোগ্রামিংয়ের ক্ষতিগুলি এড়ানো ।
CREATE TABLE ClosureTable (
ancestor_id INT NOT NULL REFERENCES FlatTable(id),
descendant_id INT NOT NULL REFERENCES FlatTable(id),
PRIMARY KEY (ancestor_id, descendant_id)
);
সমাপ্তি টেবিলের সমস্ত পাথ সংরক্ষণ করুন, যেখানে একটি নোড থেকে অন্য নোডে সরাসরি বংশ রয়েছে। প্রতিটি নোডের নিজের উল্লেখের জন্য একটি সারি অন্তর্ভুক্ত করুন। উদাহরণস্বরূপ, ডেটা সেট ব্যবহার করে আপনি আপনার প্রশ্নে দেখিয়েছেন:
INSERT INTO ClosureTable (ancestor_id, descendant_id) VALUES
(1,1), (1,2), (1,4), (1,6),
(2,2), (2,4),
(3,3), (3,5),
(4,4),
(5,5),
(6,6);
এখন আপনি নোড 1 এ শুরু করে একটি গাছ পেতে পারেন:
SELECT f.*
FROM FlatTable f
JOIN ClosureTable a ON (f.id = a.descendant_id)
WHERE a.ancestor_id = 1;
আউটপুট (মাইএসকিউএল ক্লায়েন্টে) নিম্নলিখিতগুলির মতো দেখাচ্ছে:
+----+
| id |
+----+
| 1 |
| 2 |
| 4 |
| 6 |
+----+
অন্য কথায়, নোড 3 এবং 5 বাদ দেওয়া হয়েছে, কারণ তারা নোড 1 থেকে নেমে না, একটি পৃথক শ্রেণিবিন্যাসের অংশ।
পুনরায়: তাত্ক্ষণিক শিশুদের (বা তাত্ক্ষণিক অভিভাবক) সম্পর্কে ই-সন্তুষ্টের মন্তব্য। তাত্ক্ষণিক শিশু বা পিতামাতার (বা অন্য কোনও দূরত্ব) এর জন্য বিশেষভাবে জিজ্ঞাসা করা সহজ করার জন্য আপনি " path_length
" কলামে একটি যুক্ত করতে পারেন ClosureTable
।
INSERT INTO ClosureTable (ancestor_id, descendant_id, path_length) VALUES
(1,1,0), (1,2,1), (1,4,2), (1,6,1),
(2,2,0), (2,4,1),
(3,3,0), (3,5,1),
(4,4,0),
(5,5,0),
(6,6,0);
তারপরে প্রদত্ত নোডের তাত্ক্ষণিক শিশুদের জিজ্ঞাসা করার জন্য আপনি আপনার অনুসন্ধানে একটি পদ যুক্ত করতে পারেন। এই উত্তরপুরূষ যার দ্বারা path_length
1।
SELECT f.*
FROM FlatTable f
JOIN ClosureTable a ON (f.id = a.descendant_id)
WHERE a.ancestor_id = 1
AND path_length = 1;
+----+
| id |
+----+
| 2 |
| 6 |
+----+
@ আশরাফের কাছ থেকে মন্তব্য করুন: "পুরো গাছটিকে [নাম দিয়ে] বাছাই করার পদ্ধতি কীভাবে?"
নোড 1 এর বংশধর যে সমস্ত নোডগুলি ফেরত দেওয়ার জন্য এখানে একটি উদাহরণ ক্যোয়ারী রয়েছে, ফ্ল্যাট টেবলে তাদের সাথে যুক্ত হোন যেমন নোডের অন্যান্য বৈশিষ্ট্য যেমন name
, এবং নাম অনুসারে বাছাই করুন।
SELECT f.name
FROM FlatTable f
JOIN ClosureTable a ON (f.id = a.descendant_id)
WHERE a.ancestor_id = 1
ORDER BY f.name;
@ নেট থেকে মন্তব্য পুনরায়:
SELECT f.name, GROUP_CONCAT(b.ancestor_id order by b.path_length desc) AS breadcrumbs
FROM FlatTable f
JOIN ClosureTable a ON (f.id = a.descendant_id)
JOIN ClosureTable b ON (b.descendant_id = a.descendant_id)
WHERE a.ancestor_id = 1
GROUP BY a.descendant_id
ORDER BY f.name
+------------+-------------+
| name | breadcrumbs |
+------------+-------------+
| Node 1 | 1 |
| Node 1.1 | 1,2 |
| Node 1.1.1 | 1,2,4 |
| Node 1.2 | 1,6 |
+------------+-------------+
একজন ব্যবহারকারী আজ একটি সম্পাদনার পরামর্শ দিয়েছেন। এসও মডারেটররা সম্পাদনাটি অনুমোদন করেছে, তবে আমি এটিকে বিপরীত করছি।
সম্পাদনাটি পরামর্শ দিয়েছে যে উপরের শেষ প্রশ্নের মধ্যে অর্ডার বাই দ্বারা হওয়া উচিত ORDER BY b.path_length, f.name
, সম্ভবত এটি নিশ্চিত করার জন্য যে ক্রমটি ক্রমবিন্যাসের সাথে মিলছে। তবে এটি কাজ করে না, কারণ এটি "নোড ১.১.১" এর পরে "নোড ১.২" অর্ডার করবে।
যদি আপনি ক্রমবিন্যাসকে বুদ্ধিমান উপায়ে মেলাতে চান তবে এটি সম্ভব, তবে কেবল পথের দৈর্ঘ্য অনুসারে অর্ডার দিয়ে নয়। উদাহরণস্বরূপ, মাইএসকিউএল বন্ধের সারণি শ্রেণিবদ্ধ ডাটাবেসের আমার উত্তর দেখুন - সঠিক ক্রমে কীভাবে তথ্য টানতে হবে ।