在过滤其中一列时选择对

Posted

技术标签:

【中文标题】在过滤其中一列时选择对【英文标题】:Selecting pairs while filtering one of the columns 【发布时间】:2019-08-03 03:15:49 【问题描述】:

假设我们有一个产品列表以及销售它们的城市:

Product  City
-------------
1        2
1        3
1        4
2        4

每个城市属于一个州,一个州属于一个国家。 State 和 Country 具有嵌套的编号 ID,表示它们的关系:

City   State
------------
2      1.2
3      1.3
4      2.1
State  Country
-----------
1.2      1
1.3      1
2.1      2

(X, Y) 成为城市 X 和 Y 的对。(X, Y)(Y, X) 对我来说是相同的,其中一个必须删除

首先,我想计算每对中可用的产品数量:

SELECT t1.state, t2.state, COUNT(DISTINCT product.id) FROM
 (SELECT product_city.*, city.state as state from product_city
   INNER JOIN product ON product_city.product = product.id
   INNER JOIN city ON product_city.city = city.id
 ) t1
 INNER JOIN
 (SELECT product_city.*, city.state as state from product_city
   INNER JOIN product ON product_city.product = product.id
   INNER JOIN city ON product_city.city = city.id
 ) t2
 ON t1.product = t2.product
 WHERE t1.state < t2.state
 ORDER t1.state ASC
 GROUP BY t1.state, t2.state

现在假设我只想计算状态为 2.1 的那些产品。我只能将过滤器应用于t1

(SELECT product_city.*, city.state as state from product_city
   INNER JOIN product ON product_city.product = product.id
   INNER JOIN city ON product_city.city = city.id
   WHERE city.state = '2.1'
 ) t1

但是这样我会丢失所有的对,因为t1.state 总是大于其他的。如果我将检查更改为 !=,我会得到重复的对,因为 (1.2, 1.3)(1.3, 1.2) 都被计算在内。

我该如何解决这个问题?预期的响应应该是这两行:

t1.state  t2.state  count
-------------------------
2.1       1.2       1
2.1       1.3       1

【问题讨论】:

FTR,这不是例如的副本dba.stackexchange.com/questions/161901 因为我也想过滤列表。 请发布您对问题陈述的预期数据和给定的示例数据。 另外,你如何定义一对状态 【参考方案1】:

您应该将 Product_City 表交叉连接到自身。这样,您就可以将表中的每条记录连接到表中的所有其他记录。这意味着您将让每个产品/城市组合相互匹配

FROM
(
    SELECT *
    FROM product_city p -- parent or target
    CROSS JOIN product_city c -- child or match
) product_city

然后您可以将每一方(父母和孩子)加入到各自的其他表格中以获取所有匹配项。

【讨论】:

【参考方案2】:

从将产品与州匹配开始:

select p.*, c.state
from products p join
     cities c
     on p.city = c.city;

然后,对此进行自联接:

with ps as (
      select p.*, c.state
      from products p join
           cities c
           on p.city = c.city
     )
select ps.state, ps2.state, count(*)
from ps join
     ps ps2
     on ps2.product = ps.product and ps2.state < ps.state
group by ps.state, ps2.state
order by count(*) desc;

如果您想要所有状态,即使是产品为零的状态,您可以使用 cross join 生成状态对,然后在匹配的值中使用 left join

with ps as (
      select p.*, c.state
      from products p join
           cities c
           on p.city = c.city
     ),
     ss as (
      select s.state, s2.state as state2
      from states s join
           states s2
           on s.state < s2.state
     )
select ss.state, ss.state2, count(ps2.product)
from ss left join
     ps
     on ps.state = ss.state left join
     ps ps2
     on ps2.state = ss.state2 and
        ps2.product = ps.product 
group by ss.state, ss.state2
order by count(ps2.product) desc;

【讨论】:

完美!但是,我需要它来按状态过滤对,所以它和我原来的解决方案一样。

以上是关于在过滤其中一列时选择对的主要内容,如果未能解决你的问题,请参考以下文章

R闪亮的动态DT数据表记住过滤器/排序

在选择要加入的列时加入多个 data.frame

导出Excel文件,内容量很大,打开的时候很卡,批量选择一列时,很卡很慢,文件13.6M,5W多条,求解!

Oracle---------sql 中取值两列中值最大的一列

过滤与分区列相关的列时的 Databricks 查询性能

在选择列时添加新行 # 取决于循环 #