sql امر - استبدال القيمة في حقل فارغ بعد استخدام split_part




كيفية القيود (4)

استخدام مزيج من كواليس () و نوليف ()، على سبيل المثال:

with my_table(version) as (
values
    ('10'), ('10-1'), ('10-2')
)

select 
    version, 
    split_part(version, '-', 1)::int as major, 
    coalesce(nullif(split_part(version, '-', 2), ''), '0')::int as minor
from my_table

 version | major | minor 
---------+-------+-------
 10      |    10 |     0
 10-1    |    10 |     1
 10-2    |    10 |     2
(3 rows)    

لدي عمودين، id integer version text . أحاول تحويل السلاسل في version إلى أعداد صحيحة حتى أختار الحد الأقصى (الأحدث) نسخة من المعرف.

ومع ذلك، فإن الحالة الأولى من id مخازن نفسها version . مثال:

id | version
---+--------
10 | '10'

في مقابل:

id | version
---+--------
10 | '10-0'

صفوف إضافية تتبع معرف الاتفاقية: 10، الإصدار: 10-1. إلخ.

كيف يمكنني تحقيق ذلك؟ لقد حاولت split_part() وألقي كما int . ومع ذلك، split_part(version, "-", 2) ما يبدو وكأنه سلسلة فارغة. لقد حاولت تشغيل هذا باستخدام COALESCE(splitpart..., '0') دون جدوى لأنها حاولت قراءة الحقل الفارغ عاد من قبل مؤشر الحقل 2.


للالتفاف حول سلاسل الإصدار التي ليس لها واصلة، يمكنك استخدام تعبير CASE :

CASE WHEN version LIKE '%-%'
     THEN SPLIT_PART(version, '-', 2)::int
     ELSE 0 END

الفكرة الأساسية هي استخدام رقم الإصدار، يلقي إلى إنت، عندما الواصلة موجودة، ولكن خلاف ذلك لنفترض أن الإصدار هو صفر إذا كانت الواصلة غائبة.

مع هذه العقبة خارج الطريق، الاستعلام الخاص بك الآن يقتصر فقط على استعلام ROW_NUMBER() . هنا، القسم هو id ، ويعطى الترتيب باستخدام التعبير CASE أعلاه للإصدار.

SELECT
    t.id, t.version
FROM
(
    SELECT
        id,
        CASE WHEN version LIKE '%-%'
             THEN version
             ELSE version || '-0' END AS version,
        ROW_NUMBER() OVER (PARTITION BY id
                           ORDER BY
                               CASE WHEN version LIKE '%-%'
                                    THEN SPLIT_PART(version, '-', 2)::int
                                    ELSE 0 END DESC) rn
    FROM yourTable
) t
WHERE t.rn = 1
ORDER BY t.id;

عرض هنا:

Rextester


split_part() '' ) - ليس NULL - عندما يكون الجزء المراد إرجاعه فارغ أو غير موجود. هذا هو السبب في COALESCE لا يفعل شيئا هنا. وسلسلة فارغة ( '' ) لا يوجد لديه تمثيل قيمة integer ، وبالتالي فإنه يلقي خطأ عند محاولة لإلقاء عليه.

يجب أن تكون أقصر الطرق في هذا المثال هي GREATEST(split_part( ... ) , '0') قبل الصب، لأن السلسلة الفارغة تصنف قبل أي سلسلة أخرى غير فارغة أو حتى نول (في أي لغة). ثم استخدم DISTINCT ON () للحصول على الصف مع "أكبر" version لكل id .

إعداد الاختبار

CREATE TABLE tbl (
   id      integer NOT NULL
 , version text    NOT NULL
);

INSERT INTO tbl VALUES
     (10, '10-2')
   , (10, '10-1')
   , (10, '10')      -- missing subversion
   , (10, '10-111')  -- multi-digit number
   , (11, '11-1')
   , (11, '11-0')    -- proper '0'
   , (11, '11-')     -- missing subversion but trailing '-'
   , (11, '11-2');

محاليل

SELECT DISTINCT ON (id) *
FROM   tbl
ORDER  BY id, GREATEST(split_part(version, '-', 2), '0')::int DESC;

نتيجة:

 id | version 
----+---------
 10 | 10-111
 11 | 10-2

أو يمكنك أيضا استخدام NULLIF واستخدام NULLIF NULLS LAST (بترتيب تنازلي) لفرز:

SELECT DISTINCT ON (id) *
FROM   tbl
ORDER  BY id, NULLIF(split_part(version, '-', 2), '')::int DESC NULLS LAST;

نفس النتيجة.

أو بيان CASE أكثر وضوحا:

CASE WHEN split_part(version, '-', 2) = '' THEN '0' ELSE split_part(version, '-', 2) END

دبفيدل هنا

ذات صلة:


جرب هذا

select textcat(textcat(FirstName,' '),LastName) AS Name from person;




sql postgresql split natural-sort