English 中文(简体)
要回答的SQL:根据激活/停用记录,哪些客户在给定月份处于活动状态
原标题:SQL to answer: which customers were active in a given month, based on activate/deactivate records

给定一张表

custid | date       | action
1      | 2011-04-01 | activate
1      | 2011-04-10 | deactivate
1      | 2011-05-02 | activate
2      | 2011-04-01 | activate
3      | 2011-03-01 | activate
3      | 2011-04-01 | deactivate

数据库是PostgreSQL。

我想要一个SQL查询来显示5月份任何阶段的活跃客户。

所以,在上面,这将是1和2。

我就是想不出该怎么办。有指针吗?

更新

客户2在5月期间处于活动状态,因为他在5月之前处于激活状态,但自激活后未停用。和年一样,我这个月还活着,但不是这个月出生的,我也没有死。

select distinct custid
from MyTable
where action =  active  and date >=  20110501  and date <  20110601 

这种方法不起作用,因为它只显示五月期间的激活,而不显示活动。

最佳回答

试试这个

select t2.custid from
(
-- select the most recent entry for each customer
select custid, date, action 
from cust_table t1 
where date = (select max(date) 
    from cust_table where custid = t1.custid)
) as t2
where t2.date <  2011-06-01 
-- where the most recent entry is in May or is an activate entry
-- assumes they have to have an activate entry before they get a deactivate entry 
and (date >  2011-05-01  or [action] =  activate )
问题回答

注:这将是一个起点,仅适用于2011年。

忽略任何遗留的错误,此代码(针对每个客户)将查看1)客户在5月之前的最新状态更新和2)客户是否在5月期间变得活跃?

SELECT
  Distinct CustId

FROM
 MyTable -- Start with the Main table

 -- So, was this customer active at the start of may?
 LEFT JOIN  -- Find this customer s latest entry before May of This Year
   (select 
     max(Date) 
   from
     MyTable
   where
     Date <  2011-05-01 ) as CustMaxDate_PreMay on CustMaxDate_PreMay.CustID = MyTable.CustID

 -- Return a record "1" here if the Customer was Active on this Date
 LEFT JOIN 
   (select
      1 as Bool,
      date
    from
      MyTable
   ) as CustPreMay_Activated on CustPreMay_Activated.Date = CustMaxDate_PreMay.Date and CustPreMay_Activated.CustID = MyTable.CustID and CustPreMay_Activated =  activated 

 -- Fallback plan: If the user wasn t already active at the start of may, did they turn active during may? If so, return a record here "1"
 LEFT JOIN  
   (select 
     1 as Bool 
   from
     MyTable
   where
     Date <=  2011-05-01  and Date <  2011-06-01  and action =  activated ) as TurnedActiveInMay on TurnedActiveInMay .CustID = MyTable.CustID

 -- The Magic: If CustPreMay_Activated is Null, then they were not active before May
 --            If TurnedActiveInMay is also Null, they did not turn active in May either
 WHERE
   ISNULL(CustPreMay_Activated.Bool, ISNULL(TurnedActiveInMay.Bool, 0)) = 1

注意:

您可能需要将`FROM MyTable替换为

From (Select distinct CustID from MyTable) as Customers

仅看这段代码,我就不清楚它是否会A)太慢或B)由于启动FROM子句@MYTable(每个客户可能包含许多记录)而导致错误或问题。DISTINCT子句可能会处理这个问题,但我想我会提到这个变通方法。

最后,我将让你在不同的年份完成这项工作。

在PostgreSQL 8.4+中:

WITH ActivateDates AS (
  SELECT
    custid,
    date,
    ROW_NUMBER() OVER (PARTITION BY custid ORDER BY date) AS rownum
  FROM atable
  WHERE action =  activate 
),
DeactivateDates AS (
  SELECT
    custid,
    date,
    ROW_NUMBER() OVER (PARTITION BY custid ORDER BY date) AS rownum
  FROM atable
  WHERE action =  deactivate 
),
ActiveRanges AS (
  SELECT
    a.custid,
    a.date AS activated,
    COALESCE(b.date,  21000101 ::date) AS deactivated
  FROM ActivateDates a
    LEFT JOIN DeactivateDates d ON a.custid = d.custid AND a.rownum = d.rownum
)
SELECT DISTINCT custid
FROM ActiveRanges
WHERE deactivated >  20110501 
  AND activated   <  20110601 




相关问题
摘录数据

我如何将Excel板的数据输入我的Django应用? I m将PosgreSQL数据库作为数据库。

Postgres dump of only parts of tables for a dev snapshot

On production our database is a few hundred gigabytes in size. For development and testing, we need to create snapshots of this database that are functionally equivalent, but which are only 10 or 20 ...

How to join attributes in sql select statement?

I want to join few attributes in select statement as one for example select id, (name + + surname + + age) as info from users this doesn t work, how to do it? I m using postgreSQL.

What text encoding to use?

I need to setup my PostgreSQL DB s text encoding to handle non-American English characters that you d find showing up in languages such as German, Spanish, and French. What character encoding should ...

SQL LIKE condition to check for integer?

I am using a set of SQL LIKE conditions to go through the alphabet and list all items beginning with the appropriate letter, e.g. to get all books where the title starts with the letter "A": SELECT * ...

热门标签