وظيفة نافذة PostgreSQL مع LIMIT
-
22-12-2019 - |
سؤال
يقوم الاستعلام أدناه بتجميع النتائج من first
في 4 صناديق تاريخ متباعدة بشكل متساوٍ وتجمع متوسطًا لـ the_value
في كل بن.
WITH first as(
SELECT
extract(EPOCH FROM foo.t_date) as the_date,
foo_val as the_value
FROM bar
INNER JOIN foo
ON
foo.user_id = bar.x_id
and
foo.user_name = 'xxxx'
)
SELECT bin, round(sum(bin_sum) OVER w /sum(bin_ct) OVER w, 2) AS running_avg
FROM (
SELECT width_bucket(first.the_date
, x.min_epoch, x.max_epoch, x.bins) AS bin
, sum(first.the_value) AS bin_sum
, count(*) AS bin_ct
FROM first
, (SELECT MIN(first.the_date) AS min_epoch
, MAX(first.the_date) AS max_epoch
, 4 AS bins
FROM first
) x
GROUP BY 1
) sub
WINDOW w AS (ORDER BY bin)
ORDER BY 1;
أود أن أكون قادرًا على حساب المتوسط فقط لأقل 20 شخصًا the_value
في كل سلة.من المشاركات الأخرى هنا على Stackoverflow رأيت أن هذا ممكن وربما ذلك ORDER BY the_value
و rank()
هي أفضل طريقة للقيام بذلك.لكن معاناتي هي أنني لست متأكدًا من المكان الذي يجب تعديل استعلامي الحالي لتنفيذه.
سيكون موضع تقدير أي فكرة.
بوستجرس الإصدار 9.3
المحلول
يستخدم row_number()
على كل بن.
أولا حساب رقم الصف rn
, ، ثم تطبيق WHERE rn < 21
في الخطوة التالية:
WITH first AS (
SELECT extract(EPOCH FROM foo.t_date) AS the_date
, foo_val AS the_value
FROM bar
JOIN foo ON foo.user_id = bar.x_id
AND foo.user_name = 'xxxx'
)
, x AS (
SELECT MIN(the_date) AS min_epoch
, MAX(the_date) AS max_epoch
FROM first
)
, y AS (
SELECT width_bucket(f.the_date, x.min_epoch, x.max_epoch, 4) AS bin, *
FROM first f, x
)
, z AS (
SELECT row_number() OVER (PARTITION BY bin ORDER BY the_value) AS rn, *
FROM y
)
SELECT bin, round(sum(bin_sum) OVER w / sum(bin_ct) OVER w, 2) AS running_avg
FROM (
SELECT bin
, sum(the_value) AS bin_sum
, count(*) AS bin_ct
FROM z
WHERE rn < 21 -- max 20 lowest values
GROUP BY 1
) sub
WINDOW w AS (ORDER BY bin)
ORDER BY 1;
CTEs y
و z
يمكن الخلط.بصورة مماثلة first
و x
يمكن الخلط.
لكن الأمر أوضح بهذه الطريقة.
لم يتم اختباره، لأنه ليس لدينا بيانات اختبار.
لا تنتمي إلى StackOverflow