2012-06-12 77 views
5

Tôi đang cố gắng tính toán số lượng người dùng, tích lũy cho cơ sở dữ liệu dellstore2. Nhìn vào câu trả lời ở đây, và các diễn đàn khác, tôi sử dụng nàyTổng tích lũy hàng tháng và Postgresql

select 
date_trunc('month',orderdate), 
sum(count(distinct(customerid))) 
    over (order by date_trunc('month',orderdate)) 
from orders group by date_trunc('month',orderdate) 

này trả

2004-01-01 00:00:00.0 979 
2004-02-01 00:00:00.0 1,952 
2004-03-01 00:00:00.0 2,922 
2004-04-01 00:00:00.0 3,898 
2004-05-01 00:00:00.0 4,873 
2004-06-01 00:00:00.0 5,846 
2004-07-01 00:00:00.0 6,827 
2004-08-01 00:00:00.0 7,799 
2004-09-01 00:00:00.0 8,765 
2004-10-01 00:00:00.0 9,745 
2004-11-01 00:00:00.0 10,710 
2004-12-01 00:00:00.0 11,681 

Mỗi tháng là

979 
973 
970 
976 
975 
973 
981 
972 
966 
980 
965 
971 

Nó dường như được tổng cộng là tốt, nhìn vào vài đầu tiên mặt hàng. Nhưng khi tôi chạy

select count(distinct(customerid)) from orders 

cho toàn bộ điều, tôi nhận được

8996 

mà không đồng ý với mục cuối cùng trong đầu ra đầu tiên 11.681. Tôi đoán phép tính ở trên không thể xác định tính duy nhất trong nhiều tháng. Cách nhanh nhất để tính toán này, tốt nhất là không sử dụng tự kết nối là gì?

+1

Một số khách hàng có mua nhiều thứ hơn một lần không? Trong những tháng khác nhau? –

+0

@ NikolaMarkovinović bạn nói đúng về điều đó, bạn nên đặt câu trả lời đó là một câu trả lời ... –

+0

@pOcHa Od svih gradova, moj omiljeni Niš .... :-) –

Trả lời

7

Thay vì chọn trực tiếp từ các đơn đặt hàng, bạn có thể sử dụng một subquery như vậy:

SELECT OrderDate, 
     SUM(COUNT(DISTINCT customerid)) OVER (ORDER BY OrderDate) 
FROM ( SELECT CustomerID, 
        DATE_TRUNC('MONTH', MIN(OrderDate)) AS OrderDate 
      FROM Orders 
      GROUP BY CustomerID 
     ) AS Orders 
GROUP BY OrderDate 

Tôi nghĩ rằng điều này sẽ làm việc theo yêu cầu.

http://sqlfiddle.com/#!1/7a8cc/1

EDIT

Nếu bạn vẫn cần cả hai phương pháp (tức là khác biệt và tổng chạy), bạn có thể sử dụng này:

SELECT OrderDate, 
     COUNT(DISTINCT CustomerID) AS MonthTotal, 
     SUM(COUNT(DISTINCT customerid)) OVER (ORDER BY OrderDate) AS CumulativeTotal, 
     SUM(COUNT(DISTINCT CASE WHEN OrderNumber = 1 THEN customerid END)) OVER (ORDER BY OrderDate) AS CumulativeDistinctTotal 
FROM ( SELECT CustomerID, 
        OrderDate, 
        ROW_NUMBER() OVER(PARTITION BY CustomerID ORDER BY OrderDate) AS OrderNumber 
      FROM Orders 
     ) AS Orders 
GROUP BY OrderDate 

Ví dụ ở đây:

http://sqlfiddle.com/#!1/7a8cc/10

+2

+1 - Người dơi nghĩ rất hay. – MatBailie

+0

thực sự hiệu quả và tôi không biết tại sao. :) tôi sẽ cố gắng hiểu nó. cám ơn. – user423805

+1

Việc đầu tiên hoạt động bởi vì thay vì sử dụng 'COUNT (DISTINCT CustomerID)' để loại bỏ các bản sao, các bản sao được loại bỏ bằng cách nhóm các tập dữ liệu được tính để bạn sẽ nhận được kết quả tương tự mà không có 'DISTINCT' trong số. Cách thứ hai về cơ bản giống với truy vấn ban đầu của bạn với cột 'ROW_NUMBER' bổ sung được thêm vào tập hợp, điều này được sử dụng để xác định thứ tự đầu tiên cho từng khách hàng, vì vậy có thể đếm tất cả đơn đặt hàng và khách hàng riêng biệt. – GarethD

Các vấn đề liên quan