我在一个网站上有一些数据,网站上有不同的商店部分但是当用户最后结账时,我们只通过寻找他们最近的部分内容来了解它的商店部分
例如,如果我的数据看起来像
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
答案 0 :(得分: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
答案 1 :(得分: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的评论,这似乎不是正确的方法。
答案 2 :(得分:1)
根据我的理解,“最后访问过的商店页面”应该是持久的,直到访问另一个页面或会话结束。我是在后端做这种操作的朋友。围绕add opeartion的触发器或存储过程应该能够做到。特别是添加触发器可能有效。但是您可以使用并且理想的选项在很大程度上取决于您使用的DBMS(并非所有选项都支持相同,并且性能也可能大不相同)。
我个人会在会话中坚持“访问过的最后一个商店”并将其添加到所有插页中。我认为所显示的表上的2个触发器可以做到:
除了触发器,您当然也可以使用包装这一切的存储过程,但在这种情况下IMHO触发器更干净,因为它不依赖于数据的添加方式。正常会话清理代码还将处理清理该临时数据。会话的默认值可以是“null”。您应该考虑两个触发器代码中没有会话(无论出于何种原因)的罕见情况。 当然这只是为了将来添加它。它不会追溯适用于现有表格。
如果您希望它应用于所有现有和未来的数据,视图上的计算列将是我最好的想法。至少DBMS可以对这些进行大量的缓存。但它又取决于DBMS,是否支持像计算列的视图。