从两个子查询中选择,并在另一列上加入

时间:2015-07-20 19:44:52

标签: sql postgresql

我从三个表中提取了两个问题:

t1 -sites
t2 - blues
t3 - reds

query1 -

SELECT s.site_name b.year b.value 
FROM sites s, blues b 
WHERE s.id = b.site_id AND s.site_name ='site1'

返回以下内容(例如)

| site_name  |  year  |  blues  |
| site1      |  2012  |   23.6  | 
| site1      |  2011  |   19.1  |
| site1      |  2010  |   10.2  |
| site1      |  2009  |   25.8  | 
| site1      |  2008  |   14.0  | 

查询2

SELECT s.site_name r.year r.value 
FROM sites s, reds r 
WHERE s.id = r.site_id 
AND s.site_name ='site1'

返回:

| site_name  |  year  |    reds  |
| site1      |  2012  |     14.0 | 
| site1      |  2010  |     11.0 |
| site1      |  2009  |     18.9 | 

我最终想要这个:

| site_name  |  year  |  blues  |  reds  |
| site1      |  2012  |   23.6  |   14.0 | 
| site1      |  2011  |   19.1  |        |
| site1      |  2010  |   10.2  |   11.0 |
| site1      |  2009  |   25.8  |   18.9 | 
| site1      |  2008  |   14.0  |        |

这基本上相当于一个网站的蓝调和红色表中的所有记录,即使其中一个表没有该年的记录,也会与年份相匹配。

非常感谢@vkp指出我正确的方向:CTE救援。

以下是经过测试的查询

WITH x AS (SELECT s.site_name AS name, b.year AS yr1, b.value AS blue_val
    FROM public.sites s JOIN public.blues b 
    ON  s.id = b.site_id
    WHERE s.site_name = 'Site1'
    ), y AS (SELECT s.site_name, r.year AS yr2, r.value AS red_val
    FROM public.stations s JOIN public.reds r 
    ON  s.id = r.site_id
    WHERE s.site_name = 'Site1'
    )
    SELECT x.name, x.yr1, x.blue_val, y.red_val
    FROM x LEFT JOIN y ON x.yr1 = y.yr2

3 个答案:

答案 0 :(得分:2)

SELECT s.site_name, b.year, b.value as blues, r.value as reds
FROM sites s right join blues b on s.id = b.site_id
right join reds r on s.id = r.site_id and b.year = r.year
where s.site_name ='site1'

使用CTE更新了查询:

with x as (SELECT s.site_name, b.year, b.value as blues
    FROM sites s join blues b on s.id = b.site_id
    where s.site_name ='site1') 
    , y as (SELECT s.site_name, r.year, r.value as blues
    FROM sites s join reds r on s.id = r.site_id
    where s.site_name ='site1')
    ,yrs as (select year from x union select year from y)
    select 
    case when x.site_name is not null then x.site_name 
    else y.site_name end as site_name
    , yrs.year, x.value as blue_val, y.value as red_val
    from yrs left join x on x.year = yrs.year
    left join y on y.year = yrs.year

答案 1 :(得分:0)

SELECT s.site_name b.year b.value r.value
FROM sites s
INNER JOIN blues b ON s.id = b.site_id AND s.site_name ='site1'
INNER JOIN reds r ON s.id = r.site_id AND s.site_name ='site1'

答案 2 :(得分:0)

如果语法不正确,请原谅我 - 我对Postgresql并不熟悉。

如果您可以嵌套查询:

SELECT
  s.site_name,
  i.year,
  i.blues,
  i.reds
FROM
  #sites AS s,
  (
    SELECT
      COALESCE( b.site_id, r.site_id ) AS site_id,
      COALESCE( b.year, r.year ) AS year,
      b.value AS blues,
      r.value AS reds
    FROM
      #blues AS b
      FULL OUTER JOIN #reds AS r
        ON r.year = b.year AND r.site_id = b.site_id
  ) AS i
WHERE
  s.site_name = 'site1' AND
  i.site_id = s.site_id

如果不能,请使用UNION分隔您在年内同时存在蓝色和红色的集合的连接类型,其中年份仅存在蓝色且仅存在红色这一年:

SELECT
  s.site_id,
  b.year AS year,
  b.value AS blues,
  r.value AS reds
FROM
  #sites s
  INNER JOIN #blues b
    ON b.site_id = s.site_id
  INNER JOIN #reds r
    ON r.site_id = s.site_id AND
       r.year = b.year
WHERE
  s.site_name = 'site1'
UNION
SELECT
  s.site_id,
  b.year AS year,
  b.value AS blues,
  null AS reds
FROM
  #sites s
  INNER JOIN #blues b
    ON b.site_id = s.site_id
WHERE
  s.site_name = 'site1' AND
  b.year NOT IN ( SELECT year FROM #reds WHERE #reds.site_id = s.site_id )
UNION
SELECT
  s.site_id,
  r.year AS year,
  null AS blues,
  r.value AS reds
FROM
  #sites s
  INNER JOIN #reds r
    ON r.site_id = s.site_id
WHERE
  s.site_name = 'site1' AND
  r.year NOT IN ( SELECT year FROM #blues WHERE #blues.site_id = s.site_id )