4

我在一个网站上有一些数据,该网站有不同的商店部分,但是当用户最后结账时,我们只能通过查找他们最近点击的部分来知道它是哪个商店部分

例如,如果我的数据看起来像

session, hit_number, page
a,1,homepage
a,2,generic_page
a,3,shoe_store,
a,4,buy_add_basket
a,5,buy_checkout
b,1,sock_store
b,2,shoe_store,
b,3,buy_add_to_basket
b,4,buy_checkout
c,1,homepage
c,2,sock_store
c,3,sock_store
c,4,buy_add_to_basket
c,5,home_page
c,6,shoe_store
a,5,home_page

我想坚持他们去的最后一家商店(存在并且仅当他们在网页的购买部分时(即页面名称以“购买”开头)

我期待的输出是:

session, hit_number, page
a,1,homepage,null
a,2,generic_page,null
a,3,shoe_store,null
a,4,buy_add_basket,shoe_store
a,5,buy_checkout,shoe_store
b,1,sock_store,null
b,2,shoe_store,null
b,3,buy_add_to_basket,shoe_store
b,4,buy_checkout,shoe_store
c,1,homepage,null
c,2,sock_store,null
c,3,sock_store,null
c,4,buy_add_to_basket,sock_store,
c,5,home_page,null
c,6,shoe_store,null
a,5,home_page,null
4

3 回答 3

3

我在 SQL Server 中执行此操作,但获取结果的查询在大多数供应商中都可以使用。它背后的逻辑是检查page列何时包含'buy'然后获取min值,即页面名称包含的上面的值'store'

创建和填充表:

DECLARE @table TABLE
(
    session    VARCHAR(1),
    hit_number INT,
    page       VARCHAR(50)
);
INSERT INTO @table VALUES 
('a',1,'homepage'),
('a',2,'generic_page'),
('a',3,'shoe_store'),
('a',4,'buy_add_basket'),
('a',5,'buy_checkout'),
('b',1,'sock_store'),
('b',2,'shoe_store'),
('b',3,'buy_add_to_basket'),
('b',4,'buy_checkout'),
('c',1,'homepage'),
('c',2,'sock_store'),
('c',3,'sock_store'),
('c',4,'buy_add_to_basket'),
('c',5,'home_page'),
('c',6,'shoe_store'),
('a',5,'home_page');

Select * From @table将给出以下结果:

session hit_number  page
a       1           homepage
a       2           generic_page
a       3           shoe_store
a       4           buy_add_basket
a       5           buy_checkout
b       1           sock_store
b       2           shoe_store
b       3           buy_add_to_basket
b       4           buy_checkout
c       1           homepage
c       2           sock_store
c       3           sock_store
c       4           buy_add_to_basket
c       5           home_page
c       6           shoe_store
a       5           home_page

询问:

SELECT
    session,
    hit_number,
    page,
    CASE
        WHEN page LIKE 'buy%'
        THEN MIN(CASE
                     WHEN page LIKE '%store'
                     THEN page
                     ELSE NULL
                 END) OVER(PARTITION BY session ORDER BY hit_number)
        ELSE NULL
    END AS previous_buy_page
FROM @table;

返回所需的结果:

session hit_number  page                previous_buy_page
a       1           homepage            NULL
a       2           generic_page        NULL
a       3           shoe_store          NULL
a       4           buy_add_basket      shoe_store
a       5           buy_checkout        shoe_store
a       5           home_page           NULL
b       1           sock_store          NULL
b       2           shoe_store          NULL
b       3           buy_add_to_basket   shoe_store
b       4           buy_checkout        shoe_store
c       1           homepage            NULL
c       2           sock_store          NULL
c       3           sock_store          NULL
c       4           buy_add_to_basket   sock_store
c       5           home_page           NULL
c       6           shoe_store          NULL
于 2017-08-31T14:13:56.733 回答
2

如果您的架构如下所示:

create table weblog
(session varchar(10)
,hit_number int
,page varchar(30)
);

INSERT INTO weblog VALUES 
('a',1,'homepage')
,('a',2,'generic_page')
,('a',3,'shoe_store')
,('a',4,'buy_add_basket')
,('a',5,'buy_checkout')
,('b',1,'sock_store')
,('b',2,'shoe_store')
,('b',3,'buy_add_to_basket')
,('b',4,'buy_checkout')
,('c',1,'homepage')
,('c',2,'sock_store')
,('c',3,'sock_store')
,('c',4,'buy_add_to_basket')
,('c',5,'home_page')
,('c',6,'shoe_store')
,('a',5,'home_page');

然后你想要一个 SELECT 语句,如:

SELECT "session"
, hit_number
, page
, CASE 
  WHEN page like 'buy%' THEN 
  max(CASE 
        WHEN page like '%store' THEN page 
        ELSE NULL
      END) OVER (PARTITION BY session ORDER BY hit_number)
  ELSE NULL
  END as last_store
FROM weblog;

(这是postgres 9.6,你用的是哪个数据库?)

顺便说一句,我同意@SteveKline 的评论,即这似乎不是正确的方法。

于 2017-08-28T00:56:19.480 回答
1

据我了解,“最后访问的商店页面”应该是持久化的,直到访问另一个页面或会话结束。我是在后端做这种操作的朋友。围绕添加操作的触发器或存储过程应该能够做到这一点。特别是添加触发器可能会起作用。但是您可以使用哪个选项并且是理想的选项在很大程度上取决于您使用的 DBMS(并非所有人都对这两个选项有同等的支持,性能也可能有很大不同)。

就我个人而言,我会在会话中保留“最后访问的商店页面”并将其添加到所有插入中。我认为显示表上的 2 个触发器可以做到这一点:

  • 每次将某些内容添加到此表时,都会尝试更新会话端“上次访问的页面”条目的触发器。
  • 还有一个触发器或存储过程用于将“最后访问的页面”从 Session 传输到该表的输入。

除了触发器,您当然也可以使用包含所有内容的存储过程,但恕我直言,在这种情况下触发器更干净,因为它不依赖于数据的添加方式。正常会话清理代码也将处理清理临时数据。session 的默认值可以是“null”。您应该考虑在两个触发器代码中都没有会话(无论出于何种原因)的罕见情况。当然,这只是为了将来添加它。它不会追溯应用于现有表。

如果您希望它适用于所有现有和未来的数据,那么视图上的计算列将是我最好的主意。至少 DBMS 可以对这些进行大量缓存。但它又取决于 DBMS 以及它是否支持带有计算列的视图之类的东西。

于 2017-09-02T21:09:28.433 回答