Oracle SQL查询返回首次访问属性的客户

时间:2019-04-04 07:08:16

标签: sql oracle

我有3个表:客户属性住宿。表客户包含有关客户(customer_id, name, surname, email...)的所有数据。表格属性包含所有属性(property_id, property_name...的列表,表格停留包含客户的所有较早停留(customer_id, property_id, stay_id, arrival_date, departure_date...)。

一些顾客多次入住多个酒店,而有些顾客则是第一次来。 有人可以解释一下oracle sql查询,该查询仅返回第一次在任何属性中进行样式设置的客户。

对不起,您回答晚了。 这就是我到目前为止所得到的。

表格: 客户$ A $

住宿$ B $

物业$ C $

Customer_Fragments $ D $

SELECT a.RIID_, 
  sub.CUSTOMER_ID_, 
  sub.PROPERTY_ID, 
  b.ARRIVAL_DATE, 
  c.PROPERTY_SEGMENT, 
  ROW_NUMBER() OVER (
    PARTITION BY sub.CUSTOMER_ID_, 
    sub.PROPERTY_ID 
    ORDER BY 
      sub.CUSTOMER_ID_ asc
  ) RN 
FROM 
  (
    SELECT 
      b.CUSTOMER_ID_, 
      b.PROPERTY_ID 
    FROM 
      $B$ b 
    GROUP BY 
      b.CUSTOMER_ID_, 
      b.PROPERTY_ID 
    HAVING 
      COUNT(*)= 1
  ) sub 
  INNER JOIN $A$ a ON sub.CUSTOMER_ID_ = a.CUSTOMER_ID_ 
  INNER JOIN $B$ b ON sub.CUSTOMER_ID_ = b.CUSTOMER_ID_ 
  INNER JOIN $C$ c ON sub.PROPERTY_ID = c.PROPERTY_ID 
  LEFT JOIN $D$ d ON a.RIID_ = d.RIID_ 
WHERE 
  b.ARRIVAL_DATE = TRUNC(SYSDATE + 7) 
  AND c.PROPERTY_DESTINATION = 'Destination1' 
  AND lower(c.NAME_) NOT LIKE ('unknown%') 
  AND a.NWL_PERMISSION_STATUS = 'I'  
  AND a.EMAIL_DOMAIN_ NOT IN ('abuse.com', 'guest.booking.com')
  AND (d.BLACKLISTED != 'Y' 
    or d.BLACKLISTED is null
  )

我想选择所有从今天起7天到达Destination1的客户,以告知他们一些活动。客户可以预订几个 目的地1中的属性并具有相同的到达日期(例如:我可以为我和我的妻子在属性1中预订房间,也可以为我的朋友预订属性2中的房间。我们都在同一到达日期到达目的地1)。 在这种情况下,我只想向客户发送一封信息电子邮件,而不是两封电子邮件。在这种情况下,上述SQL查询返回两行,我希望它仅返回一行(一行=一封电子邮件)。

3 个答案:

答案 0 :(得分:0)

WITH first_stays (customer_id, property_id, first_time_arrival_date, stay_no) AS
(
    SELECT s.customer_id
         , s.property_id
         , s.arrival_date AS first_time_arrival_date
         , ROW_NUMBER() OVER (PARTITION BY s.customer_id, s.property_id ORDER BY s.arrival_date) stay_no
      FROM stays s
)
SELECT c.surname AS customer_surname
     , c.name AS customer_name
     , p.property_name
     , s.first_time_arrival_date
  FROM customer c
 INNER
  JOIN first_stays s
    ON s.customer_id = c.customer_id
   AND s.stay_no = 1
 INNER
  JOIN property p
    ON p.property_id = s.property_id

第一部分WITH first_stays是CTE(公用表表达式,在Oracle中称为subquery factoring),它将使用窗口函数对到达日期排序的每对(customer_id, property_id)的停留次数进行编号ROW_NUMBER()。然后,只需将这些值连接到客户和属性表即可获取其名称或其他名称,然后应用stay_no = 1(首次入住)条件。

答案 1 :(得分:0)

总是需要发布您已经尝试编写的代码,以便我们比最终错误更能帮助您。

话虽如此,我将尽力帮助您编写完整的代码。 试试这个:

select cus.*
  from customers cus
  join stays st
    on st.customer_id = cus.customer_id
 where st.arrival_date >= YOUR_DATE --for example SYSDATE or TRUNC(SYSDATE)
   and 1 = (select count(*)
              from stays st2
             where st2.customer_id = cus.customer_id)

您尚未指定它,但是我猜测您有兴趣让初次到达日期在某个指定日期或之后的首次客户。我已将其写到WHERE clause的代码中,您应该在其中输入这样的日期。

如果您删除WHERE clause的那一部分,您将获得所有只住过一次的客户(例如,即使那个唯一住过的客户是10年前)。而且,如果您删除了代码的那部分,那么您也可以从查询中删除join on stays st表,因为该联接的唯一原因是需要访问到达日期。

如果您还需要解释代码的其他部分,请在注释中询问此答案。

希望我能帮上忙!

答案 2 :(得分:0)

如果我正确理解了这个问题,那么这不是一个复杂的查询:

select c.*
from c join
     (select s.customer_id
      from stays s
      group by s.customer_id
      having count(*) = 1
     ) s
     on s.customer_id = c.customer_id;