SQL查询内部联接返回多行

时间:2015-01-30 20:02:29

标签: java sql oracle hibernate oracle10g

我们有2张桌子; table1,table2。

  

table1

CNTY | ZIP  | SERVICE
111  | 1234 |  N
111  |      |  Y 
112  |      |  Y
     

table2

CNTY | ZIP  |
111  | 1234 |
111  | 4321 |
112  | 4433 |

我们正在使用oracle并尝试以下查询 -

SELECT t1.SERVICE
  FROM table1 t1
 WHERE t1.CNTY IN (SELECT t2.CNTY
                     FROM table2 t2
                    WHERE t2.ZIP = '4433')

返回Y是预期的行为。但是如果我们发送t2.zip='4321'它返回2行,但我们期待一行(Y)。另外,如果我们发送应返回“N”的t2.zip='1234'。但是,上面的查询返回2行。

我是一个非常新的数据库方面。我们尝试过,但无法在一个声明中得到它。有没有办法达到预期的行为?

基本上我对查询的期望是 -

  1. 应该始终从SERVICE返回table1值。如果它在ZIP中找到table1,则应返回匹配zip的SERVICE值。
  2. 如果ZIP中没有匹配的table1,那么它应该会在CNTY中找到与给定zip相关联的table2,然后取出CNTY来自table2的值,它应在SERVICE中找到匹配table1的{​​{1}}值并返回该值。
  3. 例如:对于ZIP 4321,table1中没有匹配的条目,但是在table2中4321与111相关联,因此对于table1中的111,SERVICE值为Y.因此,查询应该返回Y.

4 个答案:

答案 0 :(得分:1)

我不确定为什么你只想要一排。让我们来看看查询的作用:

SELECT t2.CNTY FROM table2 t2 WHERE t2.ZIP = '4321'

返回单个值:111,对应于以下行:

     111  | 4321 |

所以完整的查询等同于

SELECT t1.SERVICE FROM table1 t1 WHERE t1.CNTY IN (111)

然后返回这两行的服务,因为它们的CNTY都等于111:

     111  | 1234 |  N
     111  |      |  Y 

答案 1 :(得分:0)

它返回两个因为你在table1中有两行,城市111

select t1.* from
table1 t1
join table2 t2 on t2.city = t1.city and (t2.zip = t1.zip or t2.zip is null)

现在您加入了城市和邮政编码,或者没有邮政编码。

这将只返回一行,但如果有两个城市行,111并且没有邮政编码,那么它将返回2

(注意:没有测试过这个SQL - 我已经从内存中完成了它;))

答案 2 :(得分:0)

  

有没有办法达到预期的行为?

是的,您可以加入CNTYZIP上的表格。

SELECT t1.SERVICE
  FROM table1 t1, table2 t2
 WHERE t1.CNTY = t2.CNTY AND t1.ZIP = t2.ZIP
   AND t2.ZIP = '1234'

然而,上述仍然不适用于ZIP'4321'。为此,连接必须更复杂。

SELECT COALESCE(t1a.SERVICE, t1b.SERVICE) AS SERVICE
  FROM table2 t2
    LEFT JOIN table1 t1a ON t1a.CNTY = t2.CNTY AND t1a.ZIP = t2.ZIP
    LEFT JOIN table1 t1b ON t1b.CNTY = t2.CNTY AND COALESCE(t1b.ZIP, '') = ''
  WHERE t2.ZIP = '4321'

第二个查询适用于所有情况。

答案 3 :(得分:0)

select service from (
  select row_number() over (order by t1.zip nulls last) rn, service 
    from table1 t1 
      join table2 t2 on t2.cnty = t1.cnty and (t2.zip = t1.zip or t1.zip is null) 
    where coalesce(t1.zip, t2.zip) = '1234')
  where rn=1
如果row_number有两行,

join用于对记录进行排序,例如zip = 1234。 查询对每个zip都正常工作。

您也可以使用:

  select 
      case 
        when exists (select 1 from table1 where zip='1234') 
        then 
          (select service from table1 where zip='1234')
        else
          (select service from table1 where zip is null 
              and cnty = (select cnty from table2 where zip='1234')) 
    end service
    from dual

喜欢这里:

  with zips as (select '1234' zip from dual 
    union select '4321' from dual 
    union select '4433' from dual 
    union select 'TEST' from dual)
  select zips.zip, 
      case 
        when exists (select 1 from table1 where zip=zips.zip) 
        then 
          (select service from table1 where zip=zips.zip)
        else
          (select service from table1 where zip is null and cnty = 
             (select cnty from table2 where zip=zips.zip)) 
      end service
    from zips

zip     service
1234    N
4321    Y
4433    Y
TEST    null