ইচ্ছামত একটি সারণীতে রেকর্ড অর্ডার


28

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

আমি যে সাধারণ সমাধানটি দেখেছি তা হল একটি পূর্ণসংখ্যা কলাম যুক্ত করা order:

CREATE TABLE AS your_table (id, title, sort_order)
AS VALUES
  (0, 'Lorem ipsum',   3),
  (1, 'Dolor sit',     2),
  (2, 'Amet, consect', 0),
  (3, 'Elit fusce',    1);

তারপরে, আমরা সারিগুলি orderযথাযথ ক্রমে পেয়ে বাছাই করতে পারি ।

তবে এটি আনাড়ি বলে মনে হচ্ছে:

  • আমি যদি শুরুতে রেকর্ড 0 স্থানান্তরিত করতে চাই তবে আমাকে প্রতিটি রেকর্ড পুনরায় অর্ডার করতে হবে
  • আমি যদি মাঝখানে একটি নতুন রেকর্ড সন্নিবেশ করতে চাই তবে আমাকে তার পরে প্রতিটি রেকর্ড পুনরায় অর্ডার করতে হবে
  • আমি যদি কোনও রেকর্ড অপসারণ করতে চাই তবে আমাকে তার পরে প্রতিটি রেকর্ড পুনরায় অর্ডার করতে হবে

এরকম পরিস্থিতি কল্পনা করা সহজ:

  • দুটি রেকর্ড একই আছে order
  • orderরেকর্ডগুলির মধ্যে ফাঁক রয়েছে

এগুলি বেশ কয়েকটি কারণে বেশ সহজেই ঘটতে পারে।

এটি জুমলার মতো অ্যাপ্লিকেশনগুলি গ্রহণ করে:

অর্ডার দেওয়ার জন্য জুমলার পদ্ধতির উদাহরণ

আপনি তর্ক করতে পারেন যে এখানে ইন্টারফেসটি খারাপ, এবং মানুষের সরাসরি সংখ্যা সম্পাদনা করার পরিবর্তে তাদের তীর বা ড্র্যাগ-অ্যান্ড-ড্রপ ব্যবহার করা উচিত — এবং আপনি সম্ভবত সঠিক হতেন। তবে পর্দার আড়ালে একই ঘটনা ঘটছে।

কিছু লোক অর্ডার সংরক্ষণের জন্য দশমিক ব্যবহারের প্রস্তাব দিয়েছিল, যাতে আপনি আদেশ ২ এবং 3 এ রেকর্ডের মধ্যে একটি রেকর্ড সন্নিবেশ করতে "2.5" ব্যবহার করতে পারেন এবং এটি যদি কিছুটা সহায়তা করে তবে এটি তর্কসাপেক্ষে এমনকি আরও মেসিওর হয় কারণ আপনি শেষ পর্যন্ত যেতে পারেন অদ্ভুত দশমিক (আপনি কোথায় থামবেন? 2.75? 2.875? 2.8125?)

কোনও টেবিলে অর্ডার সঞ্চয় করার আরও ভাল উপায় কি নেই?


5
ঠিক যেমন তুমি জানো . । । "এই জাতীয় সিস্টেমগুলিকে" রিলেশনাল " বলার কারণ হ'ল রিলেশন শব্দটি মূলত একটি টেবিলের জন্য একটি গাণিতিক শব্দ ।" - ডেটাবেস সিস্টেমগুলির একটি ভূমিকা , সিজে তারিখ, 7 ম এড। পি 25
মাইক শেরিল 'ক্যাট রিকল'


@ মাইকশেরিল'গ্রিকাল 'যা আমি ধরিনি, আমি প্রশ্নটি পুরানো ordersএবং ডিডিএল দিয়ে স্থির করেছি ।
ইভান ক্যারল 3

উত্তর:


17

আমি যদি শুরুতে রেকর্ড 0 স্থানান্তরিত করতে চাই তবে আমাকে প্রতিটি রেকর্ড পুনরায় অর্ডার করতে হবে

না, একটি সহজ উপায় আছে।

update your_table
set order = -1 
where id = 0;

আমি যদি মাঝখানে একটি নতুন রেকর্ড সন্নিবেশ করতে চাই তবে আমাকে তার পরে প্রতিটি রেকর্ড পুনরায় অর্ডার করতে হবে

এটি সত্য, যদি না আপনি কোনও ডাটা টাইপ ব্যবহার করেন যা "মধ্যে" মানগুলিকে সমর্থন করে। ভাসা এবং সংখ্যাগত প্রকারের সাহায্যে আপনাকে 2.5 বলে একটি মান আপডেট করতে দেয়। তবে ভারচার (এন )ও কাজ করে। (ভাবুন 'এ', 'বি', 'সি'; তারপরে 'বা', 'বিবি', 'বিসি' ভাবেন))

আমি যদি কোনও রেকর্ড অপসারণ করতে চাই তবে আমাকে তার পরে প্রতিটি রেকর্ড পুনরায় অর্ডার করতে হবে

না, একটি সহজ উপায় আছে। শুধু সারি মুছুন। অবশিষ্ট সারিগুলি এখনও সঠিকভাবে বাছাই করবে।

এরকম পরিস্থিতি কল্পনা করা সহজ:

দুটি রেকর্ড একই আদেশ আছে

একটি অনন্য বাধা এটি প্রতিরোধ করতে পারে।

রেকর্ডের মধ্যে ক্রম ফাঁক আছে

ডিবিএম কীভাবে কলামে মানগুলি বাছাই করে তাতে গ্যাপগুলির কোনও প্রভাব নেই।

কিছু লোক অর্ডার সংরক্ষণের জন্য দশমিক ব্যবহারের প্রস্তাব দিয়েছিল, যাতে আপনি আদেশ ২ এবং 3 এ রেকর্ডের মধ্যে একটি রেকর্ড সন্নিবেশ করতে "2.5" ব্যবহার করতে পারেন এবং এটি যদি কিছুটা সহায়তা করে তবে এটি তর্কসাপেক্ষে এমনকি আরও মেসিওর হয় কারণ আপনি শেষ পর্যন্ত যেতে পারেন অদ্ভুত দশমিক (আপনি কোথায় থামবেন? 2.75? 2.875? 2.8125?)

আপনি যতক্ষণ না আপনাকে থামবেন না আছে আছে। ডিবিএমের নেইদশমিক বিন্দুর পরে 2, 7, বা 15 স্থান মানগুলি বাছাই করতে সমস্যা ।

আমার মনে হয় আপনার আসল সমস্যাটি হ'ল আপনি ইন্টিজার হিসাবে সাজানো ক্রমের মান দেখতে চান । আপনি এটি করতে পারেন।

create table your_table (
  id int primary key, 
  title varchar(13), 
  sort_order float
);

insert into your_table values
(0, 'Lorem ipsum', 2.0),
(1, 'Dolor sit', 1.5),
(2, 'Amet, consect', 0.0),
(3, 'Elit fusce', 1.0);

-- This windowing function will "transform" the floats into sorted integers.
select id, title,
       row_number() over (order by sort_order)
from your_table

with cte as (select *,row_number() over (order by sort_order desc) as row from test) update cte set sort_order=row;
ঝরঝরে স্বচ্ছলতার জন্য আপনি এই জাতীয়

এখানে একটি অতিরিক্ত ইঙ্গিত দেওয়া হয়েছে: আপনি যদি এটি সত্যিই নিখুঁত হতে চান তবে আপনি আরও সারি সরিয়ে ফেলছেন কিনা তা পরীক্ষা করে নেওয়া উচিত তবে আপনি ছোঁয়াচে রাখতে চান। যদি তা হয় তবে তার চেয়ে কম সংখ্যক - "ছোঁয়া" - আপডেট করুন; ডি
রুবেন বোইক

7

এটা খুব সহজ। আপনার একটি "কার্ডিনালিটি হোল" কাঠামো থাকা দরকার:

আপনার কাছে দুটি কলাম থাকতে হবে:

  1. পিকে = 32 বিট integer
  2. অর্ডার = 64 বিট bigint( না double )

সন্নিবেশ / আপডেট

  1. প্রথম নতুন রেকর্ড সন্নিবেশ করার সময় সেট করুন order = round(max_bigint / 2)
  2. টেবিলের শুরুতে serোকানোর সময় সেট করুন order = round("order of first record" / 2)
  3. টেবিলের শেষে সন্নিবেশ করার সময় order = round("max_bigint - order of last record" / 2) 4 সেট করুন ) মাঝখানে সন্নিবেশ করানোর সময় সেট করুনorder = round("order of record before - order of record after" / 2)

এই পদ্ধতির একটি খুব বড় কার্ডিনালিটি রয়েছে। আপনার যদি সীমাবদ্ধতা ত্রুটি থাকে বা আপনি যদি মনে করেন যে আপনার কাছে ছোট কার্ডিনালিটি রয়েছে তবে আপনি অর্ডার কলামটি পুনরায় তৈরি করতে পারেন (স্বাভাবিক করুন)।

সাধারণকরণের সাথে সর্বাধিক পরিস্থিতিতে (এই কাঠামোর সাহায্যে) আপনার কাছে 32 বিটের মধ্যে "কার্ডিনালিটি হোল" থাকতে পারে।

ভাসমান পয়েন্টের ধরণগুলি ব্যবহার না করার কথা মনে রাখবেন - ক্রমটি অবশ্যই একটি সুনির্দিষ্ট মান হতে হবে!


4

সাধারণত, রেকর্ডস, শিরোনাম, আইডি, বা যে নির্দিষ্ট পরিস্থিতির জন্য উপযুক্ত উপযুক্ত কিছু তথ্য অনুসারে অর্ডার করা হয়।

আপনার যদি কোনও বিশেষ ক্রম প্রয়োজন হয় তবে পূর্ণসংখ্যা কলামটি ব্যবহার করা খারাপ মনে হয় না। উদাহরণস্বরূপ, 5 তম স্থানে যাওয়ার জন্য রেকর্ডের জায়গা তৈরি করতে, আপনি এমন কিছু করতে পারেন:

update table_1 set place = place + 1 where place > 5

আশা করি আপনি কলামটি ঘোষিত করতে পারেন uniqueএবং "পরমাণু" পুনর্বিন্যাস করার পদ্ধতি থাকতে পারে। বিশদটি সিস্টেমের উপর নির্ভর করে তবে এটি সাধারণ ধারণা।


4

… এটি তর্কযোগ্যভাবে এমনকি মেসিওর কারণ আপনি অদ্ভুত দশমিকের সাথে শেষ করতে পারেন (আপনি কোথায় থামবেন? 2.75? 2.875? 2.8125?)

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

দশমিক মানগুলি ব্যবহার করার অর্থ হ'ল আইটেম জে এবং কে এর মধ্যে আইটেম এফ স্থানান্তরিত করার জন্য জে ও কে এর জন্য ক্রম মানগুলি নির্বাচন করতে হবে তবে সেগুলি গড় গড়ে তারপরে এফ আপডেট করুন দু'টি নির্বাচনী বিবৃতি এবং একটি আপডেটের বিবৃতি (সম্ভবত এড়াতে সিরিয়ালাইজড বিচ্ছিন্নতা ব্যবহার করে সম্পন্ন করা হবে) ডেডলক)।

আপনি যদি আউটপুটে ভগ্নাংশের চেয়ে পূর্ণসংখ্যা দেখতে চান তবে হয় ক্লায়েন্ট অ্যাপ্লিকেশনটিতে পূর্ণসংখ্যার গণনা করুন বা ROW_NUMBER () বা RANK () ফাংশনগুলি ব্যবহার করুন (যদি আপনার আরডিবিএমএস এগুলিকে অন্তর্ভুক্ত করে)।


1

আমার নিজের প্রকল্পে, আমি দশমিক সংখ্যা সমাধানের মতো একটি সমাধান চেষ্টা করার পরিকল্পনা করছি, তবে এর পরিবর্তে বাইট-অ্যারে ব্যবহার করছি:

def pad(x, x_len, length):
    if x_len >= length:
        return x
    else:
        for _ in range(length - x_len):
            x += b"\x00"
        return x

def order_index(_from, _to, count, length=None):
    assert _from != _to
    assert _from < _to

    if not length:
        from_len = len(_from)
        to_len = len(_to)
        length = max(from_len, to_len)

        _from = pad(_from, from_len, length)
        _to = pad(_to, to_len, length)

    from_int = int.from_bytes(_from, "big")
    to_int = int.from_bytes(_to, "big")
    inc = (to_int - from_int)//(count + 1)
    if not inc:
        length += 1
        _from += b"\x00"
        _to += b"\x00"
        return order_index(_from, _to, count, length)

    return (int.to_bytes(from_int + ((x+1)*inc), length, "big") for x in range(count))
>>> index = order_index(b"A", b"Z", 24)
>>> [x for x in index]
[b'B', b'C', b'D', b'E', b'F', b'G', b'H', b'I', b'J', b'K', b'L', b'M', b'N', b'O', b'P', b'Q', b'R', b'S', b'T', b'U', b'V', b'W', b'X', b'Y']
>>> 
>>> index = order_index(b"A", b"Z", 25)
>>> [x for x in index]
[b'A\xf6', b'B\xec', b'C\xe2', b'D\xd8', b'E\xce', b'F\xc4', b'G\xba', b'H\xb0', b'I\xa6', b'J\x9c', b'K\x92', b'L\x88', b'M~', b'Nt', b'Oj', b'P`', b'QV', b'RL', b'SB', b'T8', b'U.', b'V$', b'W\x1a', b'X\x10', b'Y\x06']

ধারণাটি হ'ল আপনি কখনই সম্ভাব্য ইন-মধ্যবর্তী মানের বাইরে চলে যেতে পারবেন না কারণ আপনার b"\x00"যদি আরও মান প্রয়োজন হয় তবে জড়িত রেকর্ডগুলিতে আপনি কেবলমাত্র যুক্ত হন। ( intপাইথন 3 এ সীমাহীন, অন্যথায় তুলনা করার জন্য আপনাকে শেষে বাইটের একটি টুকরো বেছে নিতে হবে, ধারণাটি দুটি সংলগ্ন মানের মধ্যে, পার্থক্যটি শেষের দিকে গতিবে)

যেমন, বলতে আপনি দুই রেকর্ড আছে, b"\x00"এবং b"\x01", এবং আপনি একটি রেকর্ড তাদের মধ্যে যেতে চাই। তার মাঝে কোনো উপলব্ধ মান নয় 0x00এবং 0x01তাই আপনি যোগ, b"\x00"উভয়, এবং এখন আপনি তাদের মধ্যে মান আপনি নতুন মান সন্নিবেশ করতে ব্যবহার করতে পারেন একটি গুচ্ছ আছে।

>>> records = [b"\x00", b"\x01", b"\x02"]
>>> values = [x for x in order_index(records[0], records[1], 3)]
>>> records = records + values
>>> records.sort()
>>> records
[b'\x00', b'\x00@', b'\x00\x80', b'\x00\xc0', b'\x01', b'\x02']

ডাটাবেস সহজেই এটি বাছাই করতে পারে কারণ সবকিছু লিক্সোগ্রাফিক ক্রমে শেষ হয়। আপনি যদি কোনও রেকর্ড মুছেন, এটি এখনও ক্রমযুক্ত। আমার প্রকল্পে, আমি তৈরি করেছি b"\x00"এবং b"\xff"হিসাবে FIRSTএবং LASTরেকর্ড করেছি, তবে নতুন রেকর্ডগুলি পুনরায় সংযোজন / সংযোজন করার জন্য "থেকে" এবং "থেকে" মানগুলিকে ভার্চুয়াল হিসাবে ব্যবহার করার জন্য:

>>> records = []
>>> value = next(order_index(FIRST, LAST, 1))
>>> value
b'\x7f'
>>> records.append(value)
>>> value = next(order_index(records[0], LAST, 1))
>>> value
b'\xbf'
>>> records.append(value)
>>> records.sort()
>>> records
[b'\x7f', b'\xbf']
>>> value = next(order_index(FIRST, records[0], 1))
>>> value
b'?'
>>> records.append(value)
>>> records.sort()
>>> records
[b'?', b'\x7f', b'\xbf']

0

আমি এই উত্তরটি আরও ভাল পেয়েছি । এটি সম্পূর্ণরূপে উদ্ধৃত করা:

ডাটাবেসগুলি নির্দিষ্ট জিনিসের জন্য অনুকূলিত হয়। প্রচুর সারি দ্রুত আপডেট করা তার মধ্যে একটি। এটি বিশেষভাবে সত্য হয়ে যায় যখন আপনি ডাটাবেসটির কাজটি করতে দেন।

বিবেচনা:

order song
1     Happy Birthday
2     Beat It
3     Never Gonna Give You Up
4     Safety Dance
5     Imperial March

এবং আপনি Beat Itশেষের দিকে যেতে চান , আপনার দুটি প্রশ্ন থাকবে:

update table 
  set order = order - 1
  where order >= 2 and order <= 5;

update table
  set order = 5
  where song = 'Beat It'

এবং এটাই. এটি খুব বড় সংখ্যার সাথে খুব ভালভাবে স্কেল করে। আপনার ডেটাবেজে অনুমানমূলক প্লেলিস্টে কয়েক হাজার গান রাখার চেষ্টা করুন এবং দেখুন যে গানটি এক অবস্থান থেকে অন্য স্থানে নিয়ে যেতে কত সময় নেয়। এগুলির খুব মানক রূপ রয়েছে:

update table 
  set order = order - 1
  where order >= ? and order <= ?;

update table
  set order = ?
  where song = ?

আপনার দুটি প্রস্তুত বিবৃতি রয়েছে যা আপনি খুব দক্ষতার সাথে পুনরায় ব্যবহার করতে পারেন।

এটি কিছু উল্লেখযোগ্য সুবিধা সরবরাহ করে - টেবিলের ক্রম এমন একটি বিষয় যা সম্পর্কে আপনি যুক্তিযুক্ত হতে পারেন। তৃতীয় গানে orderসর্বদা 3 এর 3 টি রয়েছে। এটির গ্যারান্টি দেওয়ার একমাত্র উপায় হ'ল ক্রম হিসাবে ক্রমাগত পূর্ণসংখ্যা ব্যবহার করা। সিউডো-লিঙ্কযুক্ত তালিকা বা দশমিক সংখ্যা বা শূন্যস্থান সহ পূর্ণসংখ্যার ব্যবহার আপনাকে এই সম্পত্তি গ্যারান্টি দেয় না; এই ক্ষেত্রে নবম সংগীত পাওয়ার একমাত্র উপায় হ'ল পুরো টেবিলটি বাছাই করা এবং নবম রেকর্ডটি পাওয়া।

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

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