我有一张表可以跟踪客户资料的变化。 Here's a simplified version:
CREATE TABLE HISTORY (
CUSTOMER_ID NUMBER(9,0),
DATE_CHANGED DATE,
ACCOUNT_TYPE VARCHAR2(20),
CONSTRAINT HISTORY_PK PRIMARY KEY (CUSTOMER_ID, DATE_CHANGED)
);
INSERT INTO HISTORY (CUSTOMER_ID, DATE_CHANGED, ACCOUNT_TYPE) VALUES (200, TO_DATE('05/01/2013 00:00:00','DD/MM/RRRR HH24:MI:SS'), 'Premium');
INSERT INTO HISTORY (CUSTOMER_ID, DATE_CHANGED, ACCOUNT_TYPE) VALUES (300, TO_DATE('17/02/2013 00:00:00','DD/MM/RRRR HH24:MI:SS'), 'Free');
INSERT INTO HISTORY (CUSTOMER_ID, DATE_CHANGED, ACCOUNT_TYPE) VALUES (100, TO_DATE('05/03/2013 00:00:00','DD/MM/RRRR HH24:MI:SS'), 'Free');
INSERT INTO HISTORY (CUSTOMER_ID, DATE_CHANGED, ACCOUNT_TYPE) VALUES (100, TO_DATE('12/03/2013 00:00:00','DD/MM/RRRR HH24:MI:SS'), 'Standard');
INSERT INTO HISTORY (CUSTOMER_ID, DATE_CHANGED, ACCOUNT_TYPE) VALUES (200, TO_DATE('22/03/2013 00:00:00','DD/MM/RRRR HH24:MI:SS'), 'Standard');
INSERT INTO HISTORY (CUSTOMER_ID, DATE_CHANGED, ACCOUNT_TYPE) VALUES (100, TO_DATE('29/03/2013 00:00:00','DD/MM/RRRR HH24:MI:SS'), 'Premium');
该数据由第三方维护。我的最终目标是在给定的时间跨度内获得每个帐户类型和月份的客户总数,但是,到目前为止,我想从更简单的事情开始 - 显示每个月/客户组合的最新帐户类型,其中记录了更改:
YEAR MONTH CUSTOMER_ID ACCOUNT_TYPE
==== ===== =========== ============
2013 1 200 Premium
2013 2 300 Free
2013 3 100 Premium
2013 3 200 Standard
此处,客户100在3月份进行了三次更改;我们显示“Premium”,因为它在3月份有最新日期。
获取所有行的查询将是:
SELECT EXTRACT(YEAR FROM DATE_CHANGED) AS YEAR,
EXTRACT(MONTH FROM DATE_CHANGED) AS MONTH,
CUSTOMER_ID, ACCOUNT_TYPE
FROM HISTORY
ORDER BY YEAR, MONTH, CUSTOMER_ID, DATE_CHANGED
是否可以使用聚合函数过滤掉不需要的行?使用分析函数更有意义吗?
(并且,在任何一种情况下,什么是适当的功能?)
编辑:我被要求提供不需要的行示例。 3月份客户100共有3行:
'05/03/2013 00:00:00', 'Free'
'12/03/2013 00:00:00', 'Standard'
'29/03/2013 00:00:00', 'Premium'
不需要的行有'Free'
和'Standard'
,因为它们不是本月最新的。
答案 0 :(得分:2)
SELECT YEAR
,MONTH
,customer_id
,max(ACCOUNT_TYPE) keep(dense_rank FIRST ORDER BY date_changed DESC) LAST_ACC
FROM (
SELECT EXTRACT(YEAR FROM DATE_CHANGED) AS YEAR,
EXTRACT(MONTH FROM DATE_CHANGED) AS MONTH,
CUSTOMER_ID,
date_changed,
account_type
FROM HISTORY
)
GROUP BY YEAR, MONTH, customer_id
ORDER BY YEAR, MONTH, CUSTOMER_ID
| YEAR | MONTH | CUSTOMER_ID | LAST_ACC |
-----------------------------------------
| 2013 | 1 | 200 | Premium |
| 2013 | 2 | 300 | Free |
| 2013 | 3 | 100 | Premium |
| 2013 | 3 | 200 | Standard |
答案 1 :(得分:2)
SELECT DISTINCT
CUSTOMER_ID,
EXTRACT(YEAR FROM DATE_CHANGED) AS YEAR,
EXTRACT(MONTH FROM DATE_CHANGED) AS MONTH,
LAST_VALUE(ACCOUNT_TYPE)
OVER(PARTITION BY CUSTOMER_ID,TO_CHAR(DATE_CHANGED,'YYYY-MM') ORDER BY DATE_CHANGED ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS ACCOUNT_TYPE
FROM HISTORY
CUSTOMER_ID YEAR MONTH ACCOUNT_TYPE
200 2013 1 Premium
300 2013 2 Free
100 2013 3 Premium
200 2013 3 Standard
答案 2 :(得分:1)
SELECT YEAR, MONTH, CUSTOMER_ID, ACCOUNT_TYPE
FROM
(
SELECT EXTRACT(YEAR FROM DATE_CHANGED) AS YEAR,
EXTRACT(MONTH FROM DATE_CHANGED) AS MONTH,
CUSTOMER_ID,
ACCOUNT_TYPE,
ROW_NUMBER() OVER (PARTITION BY CUSTOMER_ID,
EXTRACT(YEAR FROM DATE_CHANGED),
EXTRACT(MONTH FROM DATE_CHANGED)
ORDER BY EXTRACT(YEAR FROM DATE_CHANGED) DESC,
EXTRACT(MONTH FROM DATE_CHANGED) DESC,
DATE_CHANGED DESC) RN
FROM HISTORY
)
WHERE RN = 1
ORDER BY YEAR, MONTH, CUSTOMER_ID
输出
╔══════╦═══════╦═════════════╦══════════════╗
║ YEAR ║ MONTH ║ CUSTOMER_ID ║ ACCOUNT_TYPE ║
╠══════╬═══════╬═════════════╬══════════════╣
║ 2013 ║ 1 ║ 200 ║ Premium ║
║ 2013 ║ 2 ║ 300 ║ Free ║
║ 2013 ║ 3 ║ 100 ║ Premium ║
║ 2013 ║ 3 ║ 200 ║ Standard ║
╚══════╩═══════╩═════════════╩══════════════╝