使用解析函数查询同类产品

Posted

技术标签:

【中文标题】使用解析函数查询同类产品【英文标题】:Query using analytic function for similar product 【发布时间】:2021-07-05 21:52:52 【问题描述】:

我正在尝试查找查询以匹配相似的客户。

为简化情况考虑这种情况:

我有一个表格,其中包含客户姓名和购买的产品。 客户名称可以多次购买相同和/或不同的产品。

假设原始数据是:

CustomerName | ProductName
A            | p1
A            | p2
A            | p3
A            | p1
B            | p1
B            | p2
B            | p4
B            | p5
C            | p2

在我正在寻找的查询中,我想查看至少有 1 个共同购买产品的所有客户对,然后让所有产品客户 2 购买,同时显示有多少类似产品的计数(不同的产品)在客户 1 和 2 之间。根据演示原始数据,应该是:

客户 A 和 B 都购买了 p1,p2,因此在这对显示的每条记录中,他们在 CountSimilarity 中都有 2。客户 B 还购买了 p4、p5,因此它们应该是重要的输出。在 B-A 对之间,它们具有相同的 2,但客户 A 还购买了 p3,而 B 没有购买,因此这是重要的输出。 C-A 和 C-B 对也是如此

CustomerName1 | CustomerName2 | ProductName2 | CountSimilarity
A             | B             | p4           | 2
A             | B             | p5           | 2
B             | A             | p3           | 2
C             | A             | p1           | 1
C             | A             | p3           | 1
C             | B             | p1           | 1
C             | B             | p4           | 1
C             | B             | p5           | 1

在蒂姆的帮助下,在我之前的问题中,我做了以下查询,这几乎显示了我需要什么。不幸的是,计数太高 - 我需要计算不同的产品名称,这不适用于 over partition by

select distinct t1.cname, t1.pname, t2.cname, t3.pname pnamet3,
count(*) over (partition by t1.cname, t2.cname) cnt
from MyTable t1 
inner join MyTable t2 on t1.pname = t2.pname and t1.cname != t2.cname
inner join MyTable t3 on t2.cname = t3.cname and t2.pname != t3.pname

对如何处理此查询有任何建议吗?

环境是 SQL Server。

谢谢

【问题讨论】:

This questions 处理窗口函数中的distinct 您可以在这里发布您的预期结果吗?如果可能,还包括表模式和数据。 ? 【参考方案1】:

查询需要使用CROSS JOIN imo 从DISTINCT 值构建。像这样的

drop table if exists #dts;
go
create table #dts(
  CustomerName        char(1) not null,
  ProductName        char(2) not null);

insert #dts(CustomerName, ProductName) values 
('A','p1'),
('A','p2'),
('A','p3'),
('A','p1'),
('B','p1'),
('B','p2'),
('B','p4'),
('B','p5'),
('C','p2');

with
unq_cust_cte as (
    select distinct CustomerName 
    from #dts),
unq_prod_cte as (
    select distinct CustomerName, ProductName 
    from #dts),
xjoin_cte as (
    select c1.CustomerName cn1, c2.CustomerName cn2
    from unq_cust_cte c1
         cross join unq_cust_cte c2
    where c1.CustomerName<>c2.CustomerName),
similar_count_cte as (
    select x.cn1, x.cn2, count(*) similar_count
    from xjoin_cte x
         join unq_prod_cte p1 on x.cn1=p1.CustomerName
         join unq_prod_cte p2 on x.cn2=p2.CustomerName
    where p1.ProductName=p2.ProductName
    group by x.cn1, x.cn2)
select sc.*, excpt.ProductName2
from similar_count_cte sc
     cross apply (select up.ProductName
                  from unq_prod_cte up
                  where sc.cn2=up.CustomerName
                  except
                  select up.ProductName
                  from unq_prod_cte up
                  where sc.cn1=up.CustomerName) excpt(ProductName2)
order by sc.cn1, sc.cn2, excpt.ProductName2;
cn1 cn2 similar_count   ProductName2
A   B   2               p4
A   B   2               p5
B   A   2               p3
C   A   1               p1
C   A   1               p3
C   B   1               p1
C   B   1               p4
C   B   1               p5

【讨论】:

我收到了关于按顺序命名的错误,但我将其修改为 sc.cn1 而不是 x.cn1 并且有效!非常感谢你!从未见过“交叉应用”运算符,我会尝试阅读它!

以上是关于使用解析函数查询同类产品的主要内容,如果未能解决你的问题,请参考以下文章

2017.9.26JQuery源码解析一 架构与依赖

C# - Autofac解析不同类中的新实例

省略突变等待函数中的查询解析器

postgreSQL解释解析函数

需要 SQL 查询帮助以解析 BigQuery 表中的 JSON 数据

HBase高性能随机查询之道 – HFile原理解析