sql - 如果某人之前购买过相同的产品并且如果他购买过任何产品,则标记某人
问题描述
情况:
我需要添加两个标识为这样的列标志:
- 该人是否在购买日期之前购买了相同的产品。
- 该人是否在购买日期之前购买了任何其他产品。
输出应该有 5 列:
- 电子邮件
- 产品名称
- 购买日期
- 相同产品(0 = 否,1 = 是)
- 任何产品(0 = 否,1 = 是)
原始数据如下所示:
abc@gmail.com cucumber 01-02-2019
abc@gmail.com orange 04-02-2019
abc@gmail.com grapefruit 15-02-2019
cde@gmail.com blackberry 06-02-2019
cde@gmail.com lime 15-02-2019
cde@gmail.com lime 20-02-2019
zzz@gmail.com apple 02-02-2019
zzz@gmail.com apple 18-02-2019
zzz@gmail.com orange 19-02-2019
zzz@gmail.com apple 28-02-2019
客观的:
我的输出看起来像这样:
Email ProductName DatePurchased SameProduct AnyProduct
abc@gmail.com cucumber 01-02-2019 0 0
abc@gmail.com orange 04-02-2019 0 1
abc@gmail.com grapefruit 15-02-2019 0 1
cde@gmail.com blackberry 06-02-2019 0 0
cde@gmail.com lime 15-02-2019 0 1
cde@gmail.com lime 20-02-2019 1 1
zzz@gmail.com apple 02-02-2019 0 0
zzz@gmail.com apple 18-02-2019 1 1
zzz@gmail.com orange 19-02-2019 0 1
zzz@gmail.com apple 28-02-2019 1 1
我尝试了什么:我尝试了两次加入自身并使用案例语句,但我觉得这种方式效率极低。
虚拟数据:
create table #table1 (email varchar(20), productname varchar(20), datepurchased date)
insert into #table1 values
('abc@gmail.com','cucumber','2019-02-01'),
('abc@gmail.com','orange','2019-02-04'),
('abc@gmail.com','grapefruit','2019-02-15'),
('cde@gmail.com','blackberry','2019-02-06'),
('cde@gmail.com','lime','2019-02-15'),
('cde@gmail.com','lime','2019-02-20'),
('zzz@gmail.com','apple','2019-02-02'),
('zzz@gmail.com','apple','2019-02-18'),
('zzz@gmail.com','orange','2019-02-19'),
('zzz@gmail.com','apple','2019-02-28')
注意:我的实际数据有超过 1 亿行。我不确定哪种类型的查询会使数据处理尽可能快。
解决方案
获得结果的另一种选择。
我使用 ROW_NUMBER()-1 所以我们可以给第一次出现一个零值。然后我使用 SIGN() 将任何正值转换为 1。
SELECT *,
SameProduct = SIGN(ROW_NUMBER() OVER(PARTITION BY email, productname ORDER BY datepurchased)-1),
AnyProduct = SIGN(ROW_NUMBER() OVER(PARTITION BY email ORDER BY datepurchased)-1)
FROM #table1
ORDER BY email, datepurchased;
如果需要,可以将其转换为位以获得与使用 SIGN() 相同的结果,但只是在这种情况下,所有值都是正数。
SELECT *,
SameProduct = CAST(ROW_NUMBER() OVER(PARTITION BY email, productname ORDER BY datepurchased)-1 AS bit),
AnyProduct = CAST(ROW_NUMBER() OVER(PARTITION BY email ORDER BY datepurchased)-1 AS bit)
FROM #table1
ORDER BY email, datepurchased;
推荐阅读
- docker - exec形式的Docker RUN命令不起作用
- pandas - Dataframe 的真值是不明确的。使用 a.empty、a.bool()、a.item()、a.any() 或 a.all()
- github - Hexo 部署:没有连接到 Github
- javascript - 尝试在 Applescript 中记录此 javascript 变量,但其记录为 (*missing value*)
- javascript - 如果键匹配,则将对象移动到子集
- c++ - 通用引用似乎不起作用,编译器将参数作为 r 值
- docker - 任何可行的方法来使用多个 GPU,多进程和 tensorflow?
- python - numpy eig 与 svd 。为什么他们会产生不同的结果
- mysql - 按以数字开头的字符串排序 - ActiveRecord
- php - 当 data_type 不匹配时,PDO 准备好的语句返回整个表