Soru Dizi öğelerini sıralama


Giriş dizisi olarak bir dizi alan ve diziyi sıralayıp sıralanmış diziyi döndüren saklı yordam yazmak istiyorum.

Kibarca yardım.


24
2018-05-26 13:29


Menşei




Cevaplar:


Tam sayı dizisini sıralamanın en iyi yolu, intarray uzantısıBu, herhangi bir SQL formülasyonundan çok, çok daha hızlı yapacak:

CREATE EXTENSION intarray;

SELECT sort( ARRAY[4,3,2,1] );

Herhangi bir dizi türü için çalışan bir işlev:

CREATE OR REPLACE FUNCTION array_sort (ANYARRAY)
RETURNS ANYARRAY LANGUAGE SQL
AS $$
SELECT ARRAY(SELECT unnest($1) ORDER BY 1)
$$;

(Versiyonum ile değiştirdim Pavel biraz daha hızlı başka bir yerde tartışıldıktan sonra).


31
2017-10-13 06:05



Craig cevabımı silmeye oy verdim ama bir sebepten dolayı kendimi feshedemem;). Böylece cevabınızı görmek için not aldım. - Adam Gent
Yanlış olmazsam, array_sort() Yukarıdaki işlev ile tanımlanmalıdır STABLE (ya da belki IMMUTABLE) ikincisinden sonra etiketi $$. Diğer programcılar, belirli bir fonksiyonun nasıl çalıştığına dair ipuçları için bu tür volatilite etiketlerine bakabilirler. LANGUAGE SQL-Functions (tipik olarak) Postgres tarafından belirtilmiştir, ancak etiketi iki şekilde eklemeye herhangi bir zarar yoktur. - SeldomNeedy
Unutmayın ki unnest bir dizinin tüm seviyelerini geçersiz kılar: bu yüzden bir dizi diziyi sıralamaya çalışıyorsanız, beklenmedik sonuçlara sahip olursunuz: dizilerin şekli korunur, ancak değerler alt sıra olarak değil, tek tek sıralanır. - Matthew Schinckel
Merhaba, benzer bir uzantı yok bigint? - Peter Krauss


PostrgreSQL 8.4'te ve aşağıdakileri kullanabilirsiniz:

select array_agg(x) from (select unnest(ARRAY[1,5,3,7,2]) AS x order by x) as _;

Ama çok hızlı olmayacak.


Daha eski Postgres'de bu şekilde dürüst davranabilirsiniz

CREATE OR REPLACE FUNCTION unnest(anyarray)
  RETURNS SETOF anyelement AS
$BODY$
SELECT $1[i] FROM
    generate_series(array_lower($1,1),
                    array_upper($1,1)) i;
$BODY$
  LANGUAGE 'sql' IMMUTABLE

Ve bunun gibi array_agg:

CREATE AGGREGATE array_agg (
        sfunc = array_append,
        basetype = anyelement,
        stype = anyarray,
        initcond = '{}'
);

Ama daha yavaş olacak.


Ayrıca, herhangi bir sıralama algoritmasını pl / pgsql veya postgres'e takabileceğiniz başka bir dilde de uygulayabilirsiniz.


11
2018-05-26 16:03



En hızlı yol sortişlevinde intarray katkı modülü. - Craig Ringer


Sadece işlevi dürüst kullanın ():

SELECT 
    unnest(ARRAY[1,2]) AS x
ORDER BY 
    x DESC;

Görmek dizi işlevleri Pg belgelerinde.


10
2018-05-26 14:15





Bu benim için çalıştı http://www.pgsql.cz/index.php/PostgreSQL_SQL_Tricks_I#General_array_sort

CREATE OR REPLACE FUNCTION array_sort (ANYARRAY)
RETURNS ANYARRAY LANGUAGE SQL
AS $$
SELECT ARRAY(
    SELECT $1[s.i] AS "foo"
    FROM
        generate_series(array_lower($1,1), array_upper($1,1)) AS s(i)
    ORDER BY foo
);
$$;

Craig'in cevabı, Postgres'de daha çok bilgili olduğu ve daha iyi bir cevabı olduğu için lütfen bakınız. Ayrıca mümkünse cevabımı silmek için oy verin.


7
2018-05-25 05:57



Daha modern bazı tekniklerle güncellenen bu wiki makalesini aldım, bu yüzden lütfen burada gösterilen kodu değil, makaledeki kodu kullanın (ya da cevabımı görün). - Craig Ringer


PostgreSQL'in özelliklerinin çok güzel bir sergisi, David Fetter tarafından sıralama için genel prosedürdür.

CREATE OR REPLACE FUNCTION array_sort (ANYARRAY)
RETURNS ANYARRAY LANGUAGE SQL
AS $$
SELECT ARRAY(
    SELECT $1[s.i] AS "foo"
    FROM
        generate_series(array_lower($1,1), array_upper($1,1)) AS s(i)
    ORDER BY foo
);
$$;

3
2017-07-08 21:23



@MartijnPieters Benimkiyle aynı cevabın nasıl olduğuna dikkat et ama bir yıl önce cevap verdim ve nereden aldığımdan bahsettim. - Adam Gent
@AdamGent: Sanırım ilk cevap kuyruğunda bunu buldum ve sadece okunabilir hale getirmek için SQL'i yeniden biçimlendirdim. Başka bir deyişle, okunamayan formatlama dışında bir bağlamım yoktu. - Martijn Pieters♦


Herhangi bir veri türünde işe yarayacak bir çözüm arıyorsanız, bu konunun YouLikeProgramming.com.

Esasen, sizin için sıralama yapan bir saklı yordam (aşağıya kod) yaratabilirsiniz ve yapmanız gereken tek şey, dizinizi uygun şekilde sıralanması için bu yordama geçirmektir.

Sorgunuzu biraz daha taşınabilir olmak için arıyorsanız, saklı bir prosedürün kullanılmasını gerektirmeyen bir uygulama da dahil ettim.

Saklı yordamın oluşturulması

DROP FUNCTION IF EXISTS array_sort(anyarray);
CREATE FUNCTION
  array_sort(
    array_vals_to_sort anyarray
  )
  RETURNS TABLE (
    sorted_array anyarray
  )
  AS $BODY$
    BEGIN
      RETURN QUERY SELECT
        ARRAY_AGG(val) AS sorted_array
      FROM
        (
          SELECT
            UNNEST(array_vals_to_sort) AS val
          ORDER BY
            val
        ) AS sorted_vals
      ;
    END;
  $BODY$
LANGUAGE plpgsql;

Dizi değerlerini sıralama (herhangi bir dizi veri türü ile çalışır)

-- The following will return: {1,2,3,4}
SELECT ARRAY_SORT(ARRAY[4,3,2,1]);

-- The following will return: {in,is,it,on,up}
SELECT ARRAY_SORT(ARRAY['up','on','it','is','in']);

Saklı yordam olmadan dizi değerlerini sıralama

Aşağıdaki sorguda, basitçe değiştirin ARRAY[4,3,2,1] dizinizi döndüren dizi veya sorgu ile:

WITH
  sorted_vals AS (
    SELECT
      UNNEST(ARRAY[4,3,2,1]) AS val
    ORDER BY
      val
  )
SELECT
  ARRAY_AGG(val) AS sorted_array
FROM
  sorted_vals

... ya da ...

SELECT
  ARRAY_AGG(vals.val) AS sorted_arr
FROM (
  SELECT
    UNNEST(ARRAY[4,3,2,1]) AS val
  ORDER BY
    val
) AS vals

1



Daha uzun, ama Craig'in çözümden daha mı iyi? - Skippy le Grand Gourou
Sorunuzun girintisini anladığımdan emin değilim. Uygulamanızın “daha ​​iyi” olup olmadığı sizin karar vermenize bağlıdır. - Joshua Burns
Eh, Craig 5 satır çalışan bir çözüm sağlar. Yaklaşık bir yıl sonra, çok daha uzun bir çözümle bir cevap eklersiniz. Öyleyse çözümünüzün bir şekilde daha iyi olması ya da diğerlerinin olmadığı bazı durumlarda çalışması gerekir. Ben bir (Postgre) SQL acemi, bu yüzden yargılayamam, bu yüzden soruyorum. :) - Skippy le Grand Gourou
Craig'inkiyle karşılaştırdığım yöntemi karşılaştırmak için bir stres testi yapmadım. Eğer bir şansım olursa, bunu yapabilirim. :) Bu sıralama, bazılarına yararlı olabilecek bir saklı yordam oluşturmaya gerek kalmadan da gerçekleştirilebilir. - Joshua Burns
Tabii ki, sadece saklı yordamı ima ediyordum. Bir stres testi açısından değil, muhtemelen "tasarım" ya da her ne olursa olsun. Ama eğer bilmiyorsanız, sorun değil, sadece başka bir çözüm, belki bir başkası bir veya daha sonra yorum yapmak için gelecek. ;) - Skippy le Grand Gourou