具有别名的同一列上的多个连接

Posted

技术标签:

【中文标题】具有别名的同一列上的多个连接【英文标题】:multiple joins on the same column with alias 【发布时间】:2020-04-21 09:44:02 【问题描述】:

我正在尝试将多个表连接在一起。需要在同一列上连接 2 个表。但是,我需要使用指定的列别名,因为这些值仅在替换文本后才会匹配。 所以我有;

table1:
| date_time | product_quote | category_id

table2: 
| product_id | category_id

table3: 
| date | product_id | sales

table4: 
| category_id | category_name

“product_quote”的值是一个包含 product_id 的字符串。我可以通过使用 REPLACE 来解决这个问题。

想要的结果:

| year | month | week | day | product_id | quotes | sales | category_name 

我正在尝试使用以下查询,但它抱怨“product_id”不明确。 当我在 table2.product_id 上进行第三次连接时,它会执行查询,但我得到了错误的销售数字。 也不确定如何(重新)在 join 语句中使用日期别名(年、月等)。

SELECT  
    date_part('year', table1.date_time) as "year", 
    date_part('month', table1.date_time) as "month", 
    date_part('week', table1.date_time) as "week", 
    date_part('day', table1.date_time) as "day",
    REPLACE(REPLACE(table1.product_quote,'/quotes/',''),'.pdf','') as "product_id", 
    count(table1.product_quote) as quotes,
    table3.sales,
    table4.category_name
from table1
left join table2 ON "product_id" = table2.product_id
left join table4 ON table2.category_id = table4.category_id
left join table3 ON "product_id" = table3.product_id AND 
                        date_part('year', table3.date) = date_part('year', table1.date_time) AND 
                        date_part('month', table3.date) = date_part('month', table1.date_time) AND 
                        date_part('day', table3.date) = date_part('day', table1.date_time)  
where date_part('year', table1.date_time) = '2020'
group by year, month, week, day, table2.product_id, table1.product_quote, table4.category_name, table3.sales

这是我应该作为 1 个带有 3 个连接的查询执行的操作,还是我需要使用子查询? (如果是的话,怎么做?)

【问题讨论】:

【参考方案1】:

我认为您假设您是根据SELECT 部分中的“product_id”投影(或您称之为“别名”)加入的。但事实并非如此。在 SQL 中,JOIN 总是首先出现,所以JOIN 部分并不“知道”SELECT-部分。

要解决你的问题,你需要

JOIN 中使用REPLACE 表达式两次 始终在表前加上 product_id
SELECT  
    date_part('year', table1.date_time) as "year", 
    date_part('month', table1.date_time) as "month", 
    date_part('week', table1.date_time) as "week", 
    date_part('day', table1.date_time) as "day",
    REPLACE(REPLACE(table1.product_quote,'/quotes/',''),'.pdf','') as "product_id", 
    count(table1.product_quote) as quotes,
    table3.sales,
    table4.category_name
from table1
left join table2 ON REPLACE(REPLACE(table1.product_quote,'/quotes/',''),'.pdf','') = table2.product_id
left join table4 ON table2.category_id = table4.category_id
left join table3 ON REPLACE(REPLACE(table1.product_quote,'/quotes/',''),'.pdf','') = table3.product_id AND 
                        date_part('year', table3.date) = date_part('year', table1.date_time) AND 
                        date_part('month', table3.date) = date_part('month', table1.date_time) AND 
                        date_part('day', table3.date) = date_part('day', table1.date_time)  
where date_part('year', table1.date_time) = '2020'
group by year, month, week, day, table2.product_id, table1.product_quote, table4.category_name, table3.sales

至少以上是基本解决方案。 如果您使用子选择在join 之前投影table1,您也可以使用别名:

SELECT  
    t1.year,
    t1.month,
    t1.week,
    t1.day,
    t1.product_id,
    t1.quotes,
    table3.sales,
    table4.category_name
FROM
(
    SELECT 
    date_part('year', table1.date_time) as "year", 
    date_part('month', table1.date_time) as "month", 
    date_part('week', table1.date_time) as "week", 
    date_part('day', table1.date_time) as "day",
    REPLACE(REPLACE(table1.product_quote,'/quotes/',''),'.pdf','') as "product_id", 
    count(table1.product_quote) as quotes,
    from table1
) as t1
left join table2 ON t1.product_id = table2.product_id
left join table4 ON table2.category_id = table4.category_id
left join table3 ON t1.product_id = table3.product_id AND 
                        date_part('year', table3.date) = t1.year AND 
                        date_part('month', table3.date) = t1.month AND
                        date_part('day', table3.date) = t1.day
where t1.year = '2020'
group by t1.year, t1.month, t1.week, t1.day, table2.product_id, t1.product_quote, table4.category_name, table3.sales

【讨论】:

谢谢!我没有意识到连接是首先执行的(这应该很明显;)

以上是关于具有别名的同一列上的多个连接的主要内容,如果未能解决你的问题,请参考以下文章

在同一列上连接具有不同行的 2 个表

基于另一列的最大值的列上的 SQL 内连接 [重复]

LINQ to SQL:多个列上的多个连接。这可能吗?

使用 OR 和标签连接多个列上的两个表

MySQL sum 和 distinct 在具有多个连接的另一列上

Postgresql:FROM 中的子查询必须有别名 - 具有多个连接