【问题标题】:How can I make a union of temporary tables with JOIN statement?如何使用 JOIN 语句合并临时表?
【发布时间】:2021-12-26 01:02:02
【问题描述】:

通过“WITH”语句我得到了三个临时表: "october_fall10", “november_fall11”和 “december_fall12” 现在我想通过变量“member_casual”与他们执行 INNER JOIN(下面的查询),但我收到以下警报 错误消息:表名称“november_fall11”缺少数据集,而请求中未设置默认数据集。 不管我想用“december_fall12”做这件事,警报都会重复,但参考“december_fall12”

--This is Q1 from where I've got the 3 tables --

WITH october_fall10 AS
(SELECT 
   start_station_name,
   end_station_name,
   start_station_id,
   end_station_id,
   EXTRACT (DATE FROM started_at) AS start_date,
   EXTRACT(DAYOFWEEK FROM started_at) AS start_week_date,
   EXTRACT (TIME FROM started_at) AS start_time,    
   EXTRACT (DATE FROM ended_at) AS end_date,
   EXTRACT(DAYOFWEEK FROM ended_at) AS end_week_date,    
   EXTRACT (TIME FROM ended_at) AS end_time,
   DATETIME_DIFF (ended_at,started_at, MINUTE) AS total_lenght,
   member_casual
FROM 
   `ciclystic.cyclistic_seasonal_analysis.fall_202010` AS fall_analysis
ORDER BY 
   started_at DESC)
SELECT
   member_casual,
   start_week_date,
   COUNT (member_casual) AS member_casual_start,
   TIME(
   EXTRACT(hour   FROM AVG(start_time - '0:0:0')), 
   EXTRACT(minute FROM AVG(start_time - '0:0:0')), 
   EXTRACT(second FROM AVG(start_time - '0:0:0'))
   ) AS avg_start_time
FROM 
   october_fall10
GROUP BY
   start_week_date,
   member_casual
ORDER BY 
   start_week_date DESC;  
WITH november_fall11 AS
(SELECT
   start_station_name,
   end_station_name,
   start_station_id,
   end_station_id,
   EXTRACT (DATE FROM started_at) AS start_date,
   EXTRACT(DAYOFWEEK FROM started_at) AS start_week_date,
   EXTRACT (TIME FROM started_at) AS start_time,    
   EXTRACT (DATE FROM ended_at) AS end_date,
   EXTRACT(DAYOFWEEK FROM ended_at) AS end_week_date,    
   EXTRACT (TIME FROM ended_at) AS end_time,
   DATETIME_DIFF (ended_at,started_at, MINUTE) AS total_lenght,
   member_casual
FROM
   `ciclystic.cyclistic_seasonal_analysis.fall_202011` AS fall_analysis11 
ORDER BY 
   started_at DESC)
SELECT
   member_casual,
   start_week_date,
   COUNT (member_casual) AS member_casual_start,
   TIME(
   EXTRACT(hour   FROM AVG(start_time - '0:0:0')), 
   EXTRACT(minute FROM AVG(start_time - '0:0:0')), 
   EXTRACT(second FROM AVG(start_time - '0:0:0'))
   ) AS avg_start_time
FROM 
   november_fall11
GROUP BY
   start_week_date,
   member_casual
ORDER BY 
   start_week_date DESC;
WITH december_fall12 AS
(SELECT
   start_station_name,
   end_station_name,
   start_station_id,
   end_station_id,
   EXTRACT (DATE FROM started_at) AS start_date,
   EXTRACT(DAYOFWEEK FROM started_at) AS start_week_date,
   EXTRACT (TIME FROM started_at) AS start_time,    
   EXTRACT (DATE FROM ended_at) AS end_date,
   EXTRACT(DAYOFWEEK FROM ended_at) AS end_week_date,    
   EXTRACT (TIME FROM ended_at) AS end_time,
   DATETIME_DIFF (ended_at,started_at, MINUTE) AS total_lenght,
   member_casual
FROM
   `ciclystic.cyclistic_seasonal_analysis.fall_202012` AS fall_analysis11 
ORDER BY 
   started_at DESC)
SELECT
   member_casual,
   start_week_date,
   COUNT (member_casual) AS member_casual_start,
   TIME(
   EXTRACT(hour   FROM AVG(start_time - '0:0:0')), 
   EXTRACT(minute FROM AVG(start_time - '0:0:0')), 
   EXTRACT(second FROM AVG(start_time - '0:0:0'))
   ) AS avg_start_time
FROM 
   december_fall12
GROUP BY
   start_week_date,
   member_casual
ORDER BY 
   start_week_date DESC; 

--This is Q2 from where I want to get the full combination--

SELECT
       october_fall10.member_casual,
       october_fall10.start_week_date,
       october_fall10.member_casual_start,
       october_fall10.avg_start_time,
       november_fall11.member_casual,
       november_fall11.start_week_date,
       november_fall11.member_casual_start,
       november_fall11.avg_start_time,
       december_fall12.member_casual,
       december_fall12.start_week_date,
       december_fall12.member_casual_start,
       december_fall12.avg_start_time
   FROM
       ( october_fall10 JOIN (november_fall11 JOIN december_fall12 USING (member_casual)) 
       USING 
       (member_casual) )

【问题讨论】:

  • 请发布所有详细信息,而不仅仅是查询片段,以获取产生您不理解的行为的最小测试用例。它应该是完整且可执行的,而不是充满不可执行的图像。 CREATE TABLE ...; CREATE TABLE ...; INSERT ...; to provide test data; WITH cte1 AS (...), cte2 AS (...), etc ... SELECT ... FROM cte1, etc...; 包括所有这一切的最终目标,确切的预期结果,给定这个测试数据,而不仅仅是对你的 SQL 的描述。
  • 第二,UNIONJOIN 完全不同。如果您想UNION,请使用UNION。如果您想JOIN,请使用JOIN。您问题的标题表明您对自己的问题/目标感到困惑。确保以您理解的方式清楚地说明目标。如果您并不真正了解这些操作的目的,请不要使用术语“UNION”或“JOIN”。
  • 感谢您的帮助 @Jon Armstrong,但如果我真的知道您为我澄清的一切,我一开始就不会将我的疑问上传到 stackoverflow。

标签: sql google-bigquery inner-join temp-tables


【解决方案1】:

首先,当您使用WITH 创建“表”时,它不是临时表,而是公用表表达式 (CTE)。了解不同的术语很有用,因为它们的行为方式不同(就像混淆汽油和柴油不太好)

它们的不同之处之一是 CTE 不会以任何方式持久化。进行最终查询后,CTE 将超出范围,无法再次引用(在 ; 之后,CTE 已“消失”)

这意味着你想要的模式是……

WITH
  october_fall10 AS
(
  SELECT 
    start_station_name,
    end_station_name,
    start_station_id,
    end_station_id,
    EXTRACT (DATE FROM started_at) AS start_date,
    EXTRACT(DAYOFWEEK FROM started_at) AS start_week_date,
    EXTRACT (TIME FROM started_at) AS start_time,    
    EXTRACT (DATE FROM ended_at) AS end_date,
    EXTRACT(DAYOFWEEK FROM ended_at) AS end_week_date,    
    EXTRACT (TIME FROM ended_at) AS end_time,
    DATETIME_DIFF (ended_at,started_at, MINUTE) AS total_lenght,
    member_casual
  FROM 
    `ciclystic.cyclistic_seasonal_analysis.fall_202010` AS fall_analysis
),
  october_fall10_aggregate AS
(
  SELECT
     member_casual,
     start_week_date,
     COUNT(member_casual) AS member_casual_start,
     TIME(
       EXTRACT(hour   FROM AVG(start_time - '0:0:0')), 
       EXTRACT(minute FROM AVG(start_time - '0:0:0')), 
       EXTRACT(second FROM AVG(start_time - '0:0:0'))
     )
       AS avg_start_time
  FROM 
     october_fall10
  GROUP BY
     start_week_date,
     member_casual
),
  november_fall11 AS
(
  <your query here>
),
  november_fall11_aggregate AS
(
  <your query here>
),
  december_fall12 AS
(
  <your query here>
),
  december_fall12_aggregate AS
(
  <your query here>
),
SELECT
  october_fall10_aggregate.member_casual,
  october_fall10_aggregate.start_week_date,
  october_fall10_aggregate.member_casual_start,
  october_fall10_aggregate.avg_start_time,
  november_fall11_aggregate.member_casual,
  november_fall11_aggregate.start_week_date,
  november_fall11_aggregate.member_casual_start,
  november_fall11_aggregate.avg_start_time,
  december_fall12_aggregate.member_casual,
  december_fall12_aggregate.start_week_date,
  december_fall12_aggregate.member_casual_start,
  december_fall12_aggregate.avg_start_time
FROM
  october_fall10_aggregate
JOIN
  november_fall11_aggregate
    USING (member_casual)
JOIN
  december_fall12_aggregate
    USING (member_casual)

这会创建带有 _aggregate 后缀的新 CTE,然后在您的最终查询中引用它们。

  • 请注意,我还从每个 CTE 中删除了 ORDER BY
  • 这是因为 CTE(以及临时表或其他表)保留该顺序

此外,重复所有这些代码是疯狂的。将所有数据放在一个表中并编写一次代码会更好。如果你不能合并表 'as-if' 它们是一张表......

WITH
  unioned AS
(
  SELECT 202010 AS source_tbl, * FROM `ciclystic.cyclistic_seasonal_analysis.fall_202010`
  UNION ALL
  SELECT 202011 AS source_tbl, * FROM `ciclystic.cyclistic_seasonal_analysis.fall_202011`
  UNION ALL
  SELECT 202012 AS source_tbl, * FROM `ciclystic.cyclistic_seasonal_analysis.fall_202012`
),
  extraction AS
(
  SELECT 
    source_tbl,
    member_casual,
    start_station_name,
    end_station_name,
    start_station_id,
    end_station_id,
    EXTRACT (DATE FROM started_at) AS start_date,
    EXTRACT(DAYOFWEEK FROM started_at) AS start_week_date,
    EXTRACT (TIME FROM started_at) AS start_time,    
    EXTRACT (DATE FROM ended_at) AS end_date,
    EXTRACT(DAYOFWEEK FROM ended_at) AS end_week_date,    
    EXTRACT (TIME FROM ended_at) AS end_time,
    DATETIME_DIFF (ended_at,started_at, MINUTE) AS total_length
  FROM 
    unioned
)
SELECT
  member_casual,
  source_tbl,
  start_week_date,
  COUNT(member_casual) AS member_casual_start,
  TIME(
    EXTRACT(hour   FROM AVG(start_time - '0:0:0')), 
    EXTRACT(minute FROM AVG(start_time - '0:0:0')), 
    EXTRACT(second FROM AVG(start_time - '0:0:0'))
  )
    AS avg_start_time
FROM 
  extraction
GROUP BY
  member_casual,
  source_tbl,
  start_week_date
ORDER BY
  member_casual,
  source_tbl,
  start_week_date

这与您之前的格式相同,但更符合 SQL 的预期模式。

【讨论】:

  • @Rodrigo 下一步是在此答案中显示的最后一条语句的基础上执行一种 PIVOT,以解决您问题的最后一部分(如果仍然需要)。
  • 非常感谢@MatBailie 的解释!你的建议非常清楚和具有指导意义。你不仅帮我纠正了我的问题,而且我学到了。干杯。
猜你喜欢
  • 2014-02-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-19
相关资源
最近更新 更多