PostgreSQL
 sql >> डेटाबेस >  >> RDS >> PostgreSQL

समय सीमा के अनुसार अलग-अलग उपयोगकर्ता समूह चुनें

सभी गिनें पंक्तियाँ

SELECT date, '1_D' AS time_series,  count(DISTINCT user_id) AS cnt
FROM   uniques
GROUP  BY 1

UNION  ALL
SELECT DISTINCT ON (1)
       date, '2_W', count(*) OVER (PARTITION BY week_beg ORDER BY date)
FROM   uniques

UNION  ALL
SELECT DISTINCT ON (1)
       date, '3_M', count(*) OVER (PARTITION BY month_beg ORDER BY date)
FROM   uniques
ORDER  BY 1, time_series

प्रति दिन DISTINCT उपयोगकर्ता

प्रत्येक उपयोगकर्ता को प्रति दिन केवल एक बार गिनने के लिए, CTE DISTINCT ON . के साथ :

WITH x AS (SELECT DISTINCT ON (1,2) date, user_id FROM uniques)
SELECT date, '1_D' AS time_series,  count(user_id) AS cnt
FROM   x
GROUP  BY 1

UNION ALL
SELECT DISTINCT ON (1)
       date, '2_W'
      ,count(*) OVER (PARTITION BY (date_trunc('week', date + 1)::date - 1)
                      ORDER BY date)
FROM   x

UNION ALL
SELECT DISTINCT ON (1)
       date, '3_M'
      ,count(*) OVER (PARTITION BY date_trunc('month', date) ORDER BY date)
FROM   x
ORDER BY 1, 2

DISTINCT उपयोगकर्ता गतिशील समयावधि में

आप हमेशा सहसंबंधित उपश्रेणियों का सहारा ले सकते हैं . बड़ी तालिकाओं के साथ धीमे होने की प्रवृत्ति रखें!
पिछली क्वेरी के आधार पर निर्माण:

WITH du AS (SELECT date, user_id FROM uniques GROUP BY 1,2)
    ,d  AS (
    SELECT date
          ,(date_trunc('week', date + 1)::date - 1) AS week_beg
          ,date_trunc('month', date)::date AS month_beg
    FROM   uniques
    GROUP  BY 1
    )
SELECT date, '1_D' AS time_series,  count(user_id) AS cnt
FROM   du
GROUP  BY 1

UNION ALL
SELECT date, '2_W', (SELECT count(DISTINCT user_id) FROM du
                     WHERE  du.date BETWEEN d.week_beg AND d.date )
FROM   d
GROUP  BY date, week_beg

UNION ALL
SELECT date, '3_M', (SELECT count(DISTINCT user_id) FROM du
                     WHERE  du.date BETWEEN d.month_beg AND d.date)
FROM   d
GROUP  BY date, month_beg
ORDER  BY 1,2;

SQL Fiddle तीनों समाधानों के लिए।

dense_rank() के साथ तेज़

@Clodoaldo एक बड़े सुधार के साथ आया:विंडो फ़ंक्शन dense_rank() . यहाँ एक अनुकूलित संस्करण के लिए एक और विचार है। दैनिक डुप्लिकेट को तुरंत बाहर करना और भी तेज़ होना चाहिए। प्रति दिन पंक्तियों की संख्या के साथ प्रदर्शन लाभ बढ़ता है।

सरलीकृत और स्वच्छ डेटा मॉडल . पर निर्माण - बिना किसी अतिरिक्त कॉलम के- day date . के बजाय कॉलम नाम के रूप में

date एक मानक SQL में आरक्षित शब्द है और PostgreSQL में एक मूल प्रकार का नाम और पहचानकर्ता के रूप में उपयोग नहीं किया जाना चाहिए।

CREATE TABLE uniques(
   day date     -- instead of "date"
  ,user_id int
);

बेहतर क्वेरी:

WITH du AS (
   SELECT DISTINCT ON (1, 2)
          day, user_id 
         ,date_trunc('week',  day + 1)::date - 1 AS week_beg
         ,date_trunc('month', day)::date         AS month_beg
   FROM   uniques
   )
SELECT day, count(user_id) AS d, max(w) AS w, max(m) AS m
FROM  (
    SELECT user_id, day
          ,dense_rank() OVER(PARTITION BY week_beg  ORDER BY user_id) AS w
          ,dense_rank() OVER(PARTITION BY month_beg ORDER BY user_id) AS m
    FROM   du
    ) s
GROUP  BY day
ORDER  BY day;

SQL Fiddle 4 तेज वेरिएंट के प्रदर्शन का प्रदर्शन। यह आपके डेटा वितरण पर निर्भर करता है जो आपके लिए सबसे तेज़ है।
ये सभी सहसंबद्ध उपश्रेणियों के संस्करण से लगभग 10 गुना तेज़ हैं (जो सहसंबद्ध उपश्रेणियों के लिए बुरा नहीं है)।



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. अगर क्वेरी के मामले में नेस्टेड पोस्टग्रेज करता है

  2. कैसे तन () PostgreSQL में काम करता है

  3. postgresql में रिटर्निंग ऑर्डर अपडेट करें

  4. जॉइन के बाद ग्रुप या DISTINCT डुप्लीकेट लौटाता है

  5. त्रुटि:INTO में या उसके निकट INTO को एक से अधिक बार निर्दिष्ट किया गया