在过滤其中一列时选择对
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;
【讨论】:
完美!但是,我需要它来按状态过滤对,所以它和我原来的解决方案一样。以上是关于在过滤其中一列时选择对的主要内容,如果未能解决你的问题,请参考以下文章
导出Excel文件,内容量很大,打开的时候很卡,批量选择一列时,很卡很慢,文件13.6M,5W多条,求解!