كيفية فرز وعرض قوائم مختلطة من Alphas والأرقام كما يتوقع المستخدمون؟
-
23-08-2019 - |
سؤال
طلبنا لديه CustomerNumber
حقل. لدينا المئات من الأشخاص المختلفين الذين يستخدمون النظام (لكل منها تسجيل الدخول الخاص بهم وقائمة خاصة بهم CustomerNumber
س). قد يكون لدى المستخدم الفردي أكثر من 100،000 عميل. كثيرون لديهم أقل من 100.
بعض الناس وضعون الأرقام الفعلية فقط في حقول رقم العملاء، بينما يستخدم الآخرون مزيجا من الأشياء. يتيح النظام 20 حرفا يمكن أن يكون AZ أو 0-9 أو اندفاعة وتخزين هذه في varchar2 (20). يتم إجراء أي شيء أحرف صغيرة قبل تخزينه.
الآن، دعنا نقول أن لدينا تقرير بسيط يسرد جميع العملاء لمستخدم معين، مرتبة حسب رقم العميل. على سبيل المثال
SELECT CustomerNumber,CustomerName
FROM Customer
WHERE User = ?
ORDER BY CustomerNumber;
هذا حلا ساذج لأن الأشخاص الذين يستخدمون الأرقام فقط لا يريدون رؤية فرز أبجدي عادي (حيث يأتي "10" قبل "9").
لا أرغب في طرح أي أسئلة غير ضرورية حول بياناتها.
أستخدم Oracle، لكنني أعتقد أنه سيكون من المثير للاهتمام رؤية بعض الحلول لقواعد البيانات الأخرى. يرجى تضمين قاعدة البيانات التي تعمل إجابتك.
ما رأيك في أفضل طريقة لتنفيذ هذا؟
المحلول
في أوراكل 10G:
SELECT cust_name
FROM t_customer c
ORDER BY
REGEXP_REPLACE(cust_name, '[0-9]', ''), TO_NUMBER(REGEXP_SUBSTR(cust_name, '[0-9]+'))
هذا سيفرض من خلال الحدوث الأول للعدد، وليس فيما يتعلق بموقعه، أي:
customer1 < customer2 < customer10
cust1omer ? customer1
cust8omer1 ? cust8omer2
, ، اين ا ?
يعني أن النظام غير محدد.
هذا يكفي لمعظم الحالات.
لإجبار ترتيب الفرز في حالة 2
, ، يمكنك إضافة REGEXP_INSTR(cust_name, '[0-9]', n)
ل ORDER BY
قائمة n
مرات، إجبار النظام على ظهور أول n
-ذ (2nd
, 3rd
إلخ.) مجموعة من الأرقام.
لإجبار ترتيب الفرز في حالة 3
, ، يمكنك إضافة TO_NUMBER(REGEXP_SUBSTR(cust_name, '[0-9]+', n))
ل ORDER BY
قائمة n
مرات، إجبار ترتيب n
-ذ. مجموعة من الأرقام.
في الممارسة العملية، استعلام كتبت كافية.
يمكنك إنشاء فهرس يستند إلى الدعامات على هذه التعبيرات، ولكن ستحتاج إلى إجباره على تلميح، ومرحلة واحدة SORT ORDER BY
سيتم تنفيذها على أي حال، كما CBO
لا تثق مؤشرات قاعدة الوظيفة بما يكفي للسماح ORDER BY
عليهم.
نصائح أخرى
ربما يكون أفضل رهان لديك هو حساب عمود منفصل مسبقا واستخدام ذلك لطلب رقم العميل واستخدامه لعرضه. من المحتمل أن ينطوي ذلك على الحشو 0 أي أعداد صحيحة داخلية إلى طول ثابت.
الاحتمال الآخر هو القيام بفرز ما بعد الاختيار على النتائج التي تم إرجاعها.
لقد وضع جيف أونوود بلوق نشر حول كيفية حساب بعض الأشخاص أوامر الفرز الصديقة الإنسانية.
هل يمكن أن يكون لديك عمود رقمي [customerernumberint] التي يتم استخدامها فقط عندما يكون عامل التخصيص الرقمي (NULL خلاف ذلك)، ثم
ORDER BY CustomerNumberInt, CustomerNumber
1] اعتمادا على كيفية معالجة إصدار SQL الخاص بك Nulls بالترتيب الخاص بك قد ترغب في التقصير في التقصير إلى الصفر (أو اللانهاية!)
لدي موقف مروع مماثل وتطوير وظيفة فظيعة بشكل مناسب للتعامل معها (SQLServer)
في وضعي، لدي جدول من "الوحدات" (هذا نظام تتبع العمل للطلاب، لذلك تمثل وحدة في هذا السياق دورة يقوم بها). تحتوي الوحدات لديها رمز، والذي بالنسبة للجزء الأكبر من الأكواه، ولكن لأسباب مختلفة تم تصنيعه varchar وقررت بادئة بعضها حتى 5 أحرف. لذلك يتوقعون 53،123،237،356 للفرز بشكل طبيعي، ولكن أيضا T53، T123، T237، T356
Unitcode هو nvarchar (30)
إليك هيئة الوظيفة:
declare @sortkey nvarchar(30)
select @sortkey =
case
when @unitcode like '[^0-9][0-9]%' then left(@unitcode,1) + left('000000000000000000000000000000',30-(len(@unitcode))) + right(@unitcode,len(@unitcode)-1)
when @unitcode like '[^0-9][^0-9][0-9]%' then left(@unitcode,2) + left('000000000000000000000000000000',30-(len(@unitcode))) + right(@unitcode,len(@unitcode)-2)
when @unitcode like '[^0-9][^0-9][^0-9][0-9]%' then left(@unitcode,3) + left('000000000000000000000000000000',30-(len(@unitcode))) + right(@unitcode,len(@unitcode)-3)
when @unitcode like '[^0-9][^0-9][^0-9][^0-9][0-9]%' then left(@unitcode,4) + left('000000000000000000000000000000',30-(len(@unitcode))) + right(@unitcode,len(@unitcode)-4)
when @unitcode like '[^0-9][^0-9][^0-9][^0-9][^0-9][0-9]%' then left(@unitcode,5) + left('000000000000000000000000000000',30-(len(@unitcode))) + right(@unitcode,len(@unitcode)-5)
when @unitcode like '%[^0-9]%' then @unitcode
else left('000000000000000000000000000000',30-len(@unitcode)) + @unitcode
end
return @sortkey
أردت أن أطلق النار على نفسي في الوجه بعد كتابة ذلك، ومع ذلك فإنه يعمل ويبدو أنه لا يقتل الخادم عند تشغيله.
لقد استخدمت هذا في SQL Server وتعمل بشكل رائع: هنا الحل هو وسادة القيم الرقمية بحرف موجود في المقدمة بحيث تكون كلها من نفس طول السلسلة.
فيما يلي مثال باستخدام هذا النهج:
select MyCol
from MyTable
order by
case IsNumeric(MyCol)
when 1 then Replicate('0', 100 - Len(MyCol)) + MyCol
else MyCol
end
يجب استبدال 100 بالطول الفعلي لهذا العمود.