PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Benötigen Sie eine SQL-Optimierung (vielleicht ist DISTINCT ON der Grund?)

Aggregatfunktion für mehrdimensionale Arrays

Ich nehme an, Sie erstellen ein zweidimensionales Array dafür. Das ist einfacher zu handhaben als ein ARRAY of record . Standard array_agg() kann keine mehrdimensionalen Arrays aggregieren. Aber Sie können dafür ziemlich einfach Ihre eigene Aggregatfunktion schreiben:

CREATE AGGREGATE array_agg_mult (anyarray)  (
    SFUNC     = array_cat
   ,STYPE     = anyarray
   ,INITCOND  = '{}'
);

Lesen Sie die Erklärung in dieser verwandten Antwort:
Daten in einem Postgres-Array auswählen

Abfrage

SELECT DISTINCT ON (p)
       p, groundtruth, array_agg_mult(ARRAY[ARRAY[anchor_id, id]]) AS ids
FROM (
   SELECT DISTINCT ON (ps.p, m.groundtruth, m.anchor_id)
          ps.p, m.groundtruth, m.anchor_id, m.id
   FROM  (SELECT unnest(point_array) AS p) AS ps
   JOIN   measurement m ON ST_DWithin(ps.p, m.groundtruth, distance)
   ORDER  BY ps.p, m.groundtruth, m.anchor_id, random()
   ) x
GROUP  BY p, groundtruth
ORDER  BY p, random();
  • Unterabfrage x erhält eindeutige anchor_id pro (p, groundtruth) und wählt eine zufällige Zeile aus, wenn mehrere Peers vorhanden sind. So entsteht die Verbindung anchor_id - id bleibt intakt.

  • Die äußere Abfrage aggregiert ein zweidimensionales Array, wie Sie es sich gewünscht haben, geordnet nach anchor_id . Wenn Sie anchor_id haben möchten zufällig geordnet, verwenden Sie noch einmal zufällig:

    array_agg_mult(ARRAY[ARRAY[anchor_id, id]] ORDER BY random())
    
  • Und schließlich das DISTINCT ON wählt nur 1 groundtruth aus pro p , wieder zufällig.