自上次购买以来的天数

问题描述 投票:0回答:1

我有一个正在运行的查询,但我遇到了一些问题,我希望有人可以帮助我。

首先,我想做一个 JOIN 以在输出中包含客户的名字和姓氏。

其次,我想包含 customer_id 5,它没有数据,并且这些列应该为 NULL。

最后,我想包括自客户上次购买以来经过的天数。

以下是我的测试案例和尝试。任何帮助将不胜感激。



ALTER SESSION SET NLS_TIMESTAMP_FORMAT = 'DD-MON-YYYY  HH24:MI:SS.FF';

 ALTER SESSION SET NLS_DATE_FORMAT = 'DD-MON-YYYY HH24:MI:SS';

CREATE TABLE customers 
(CUSTOMER_ID, FIRST_NAME, LAST_NAME) AS
SELECT 1, 'Faith', 'Aaron' FROM DUAL UNION ALL
SELECT 2, 'Lisa', 'Saladino' FROM DUAL UNION ALL
SELECT 3, 'Micheal', 'Mazzarone' FROM DUAL UNION ALL
SELECT 4, 'Joseph', 'Zanzone' FROM DUAL UNION ALL
SELECT 5, 'Sandy', 'Herring' FROM DUAL;

ALTER TABLE customers 
ADD CONSTRAINT customers_pk PRIMARY KEY (customer_id);

CREATE TABLE items 
(PRODUCT_ID, PRODUCT_NAME, PRICE) AS
SELECT 100, 'Black Shoes', 79.99 FROM DUAL UNION ALL
SELECT 101, 'Brown Pants', 111.99 FROM DUAL UNION ALL
SELECT 102, 'White Shirt', 10.99 FROM DUAL;

ALTER TABLE items 
ADD CONSTRAINT items_pk PRIMARY KEY (product_id);

create table purchases(
  ORDER_ID NUMBER GENERATED BY DEFAULT AS IDENTITY (START WITH 1) NOT NULL,
  customer_id   number, 
  PRODUCT_ID NUMBER, 
  QUANTITY NUMBER, 
  purchase_date timestamp
);

ALTER TABLE purchases 
ADD CONSTRAINT order_pk PRIMARY KEY (order_id);

ALTER TABLE purchases ADD CONSTRAINT customers_fk FOREIGN KEY (customer_id) REFERENCES customers(customer_id);

ALTER TABLE purchases ADD CONSTRAINT items_fk FOREIGN KEY (PRODUCT_ID) REFERENCES items(product_id);

insert  into purchases (customer_id, product_id, quantity, purchase_date) 
SELECT 3, 102, 4,TIMESTAMP '2022-12-22 21:44:35' + NUMTODSINTERVAL ( LEVEL * 2, 'DAY') FROM    dual
CONNECT BY  LEVEL <= 15 UNION ALL 
select 1, 101,3, date '2023-03-29' + level * interval '2' day from dual
          connect by level <= 12
union all
select 2, 101,2, date '2023-01-15' + level * interval '8' hour from dual
          connect by level <= 15
union all
select 2, 102,2,date '2023-04-13' + level * interval '1 1' day to hour from dual
          connect by level <= 11
union all
select 3, 101,2, date '2023-02-01' + level * interval '1 05:03' day to minute from dual
          connect by level <= 10
union all
select 3, 101,1, date '2023-04-22' + level * interval '23' hour from dual
          connect by level <= 23
union all
select 3, 100,1,  date '2022-03-01' + level * interval '1 00:23:05' day to second from dual
          connect by level <= 15
union all
select 4, 102,1, date '2023-01-01' + level * interval '5' hour from dual
          connect by level <= 60;

SELECT
    customer_id, 
/*
    q.first_name,
    q.last_name,
*/
    Num_Orders,
     purchase_date AS    Last_Purchase_Date, 
order_id AS Last_Order_ID
FROM ( 
     SELECT p.*,
         COUNT( order_id ) OVER ( PARTITION BY customer_id ) AS Num_Orders,   
       ROW_NUMBER() OVER ( PARTITION BY customer_id ORDER BY purchase_date DESC, 
order_id DESC ) AS rn 
   FROM purchases p
) q
/*
join purchases p on q.customer_id = p.customer_id  
*/
WHERE rn = 1
ORDER BY customer_id;

sql oracle join rank
1个回答
1
投票

一个选择是

  • 使用 CTE(或子查询)获取每个客户的最后购买日期。
  • 然后将其外部连接到客户表,以便您获取尚未购买任何商品的客户的信息。
  • 自上次购买以来的天数:从 systimestamp 中减去上次购买日期(实际上是
    时间戳
    )并从中提取天数

SQL> with last_purchase_per_customer as
  2    (select p.customer_id, max(p.purchase_date) max_purchase_date
  3     from purchases p
  4     group by p.customer_id
  5    )
  6  select c.customer_id, c.first_name, c.last_name, p.max_purchase_date,
  7    extract(day from (systimestamp - p.max_purchase_date)) as number_of_days
  8  from customers c left join last_purchase_per_customer p on p.customer_id = c.customer_id
  9  order by c.customer_id;

CUSTOMER_ID FIRST_N LAST_NAME MAX_PURCHASE_DATE                  NUMBER_OF_DAYS
----------- ------- --------- ---------------------------------- --------------
          1 Faith   Aaron     22-APR-2023  00:00:00.000000                  105
          2 Lisa    Saladino  24-APR-2023  11:00:00.000000                  103
          3 Micheal Mazzarone 14-MAY-2023  01:00:00.000000                   83
          4 Joseph  Zanzone   13-JAN-2023  12:00:00.000000                  204
          5 Sandy   Herring

SQL>

[编辑] 如果您想获取任意数量的最后交易,请修改 CTE 以按购买日期按降序排列每个客户,然后 - 在主查询中 - 仅获取所需数量的交易。还有额外的

where
条件 (
or p.rnk is null
) 可以处理未购买任何东西的顾客。

SQL> with purchases_per_customer as
  2    (select p.customer_id,
  3       p.purchase_date,
  4       rank() over (partition by p.customer_id order by p.purchase_date desc) rnk
  5     from purchases p
  6    )
  7  select c.customer_id, c.first_name, c.last_name, p.purchase_date,
  8    extract(day from (systimestamp - p.purchase_date)) as number_of_days
  9  from customers c left join purchases_per_customer p on p.customer_id = c.customer_id
 10  where p.rnk <= &par_number_of_transactions
 11     or p.rnk is null
 12  order by c.customer_id, p.purchase_date desc;
Enter value for par_number_of_transactions: 3

CUSTOMER_ID FIRST_NAME  LAST_NAME PURCHASE_DATE                       NUMBER_OF_DAYS
----------- ----------- --------- ----------------------------------- --------------
          1 Faith       Aaron     22-APR-2023  00:00:00.000000                   106
          1 Faith       Aaron     20-APR-2023  00:00:00.000000                   108
          1 Faith       Aaron     18-APR-2023  00:00:00.000000                   110
          2 Lisa        Saladino  24-APR-2023  11:00:00.000000                   104
          2 Lisa        Saladino  23-APR-2023  10:00:00.000000                   105
          2 Lisa        Saladino  22-APR-2023  09:00:00.000000                   106
          3 Micheal     Mazzarone 14-MAY-2023  01:00:00.000000                    84
          3 Micheal     Mazzarone 13-MAY-2023  02:00:00.000000                    85
          3 Micheal     Mazzarone 12-MAY-2023  03:00:00.000000                    86
          4 Joseph      Zanzone   13-JAN-2023  12:00:00.000000                   205
          4 Joseph      Zanzone   13-JAN-2023  07:00:00.000000                   205
          4 Joseph      Zanzone   13-JAN-2023  02:00:00.000000                   205
          5 Sandy       Herring

13 rows selected.

SQL>
© www.soinside.com 2019 - 2024. All rights reserved.