如何从连接表中为每个主键项选择一条记录?

时间:2014-07-29 14:21:11

标签: java oracle

我有两个名为Hotels和Description的表。描述表包含每家酒店的描述。

  • 在hotels表中,id和city_id一起构成主键(id本身不是主键)
  • 在描述表上,每家酒店最多可以有8种描述类型(一般,位置,房间,外观,请注意,包括在内,大厅)

我想使用Hotel表和Description表更新主表。对于酒店表中的每条记录,我应该只向主表中插入一行。当我执行左外连接时,酒店表中的每个记录都会生成多个记录,因为一个酒店有0个或更多描述类型。

我想从描述表中为每个酒店选择一个描述,它不是第一个描述。 (如果是,我可以使用this one)。相反,我有描述类型的优先顺序。首先,我需要检查是否存在“一般”描述。如果有,那么应该是主表的描述,并且应该跳过酒店的剩余描述。如果“常规”描述类型不可用,那么我想检查“位置”描述类型是否可用等等。

我试图为此编写Oracle SQL查询,但它并没有完全符合我的要求。

enter image description here

以下是我用来连接两个表的查询(每个酒店有多行)。如何按照上述指南过滤每个酒店的一行?

代码:

    SELECT HOTEL_DETAILS.*,
    Description.Desc_type,
    Description.description
    FROM
     (SELECT Hotel.id,
             Hotel.city_id,
             Hotel.hotel_name,         
             City.country_code
           FROM Hotel
           LEFT OUTER JOIN City
           ON Hotel.city_id=City.city_id
     ) HOTEL_DETAILS
   LEFT OUTER JOIN Description
   ON HOTEL_DETAILS.id    =Description.id
   AND HOTEL_DETAILS.city_id    = Description.city_id

我尝试使用DECODE函数,但似乎不能完成这项工作。

2 个答案:

答案 0 :(得分:1)

您可以在sql中使用 CASE 表达式来为描述类型命名,按此顺序排序,然后使用您提到的链接获取组中的第一个。像下面的东西;

SELECT HOTEL_DETAILS.*,
    CASE Description.Desc_type
      WHEN 'general' THEN 0
      WHEN 'location' THEN 1
      WHEN 'rooms' THEN 2
      WHEN 'lobby' THEN 3
      ELSE 99 
    END desc_order,
    Description.description
    FROM
     (SELECT Hotel.id,
             Hotel.city_id,
             Hotel.hotel_name,         
             City.country_code
           FROM Hotel
           LEFT OUTER JOIN City
           ON Hotel.city_id=City.city_id
     ) HOTEL_DETAILS
   LEFT OUTER JOIN Description
   ON HOTEL_DETAILS.id    =Description.id
   AND HOTEL_DETAILS.city_id    = Description.city_id
   ORDER BY HOTEL_DETAILS.id, HOTEL_DETAILS.city_id, desc_order

答案 1 :(得分:1)

    SELECT dtl.id,
           dtl.city_id,
           dtl.hotel_name,
           dtl.country_code,
           min(dsc.desc_type)   KEEP (DENSE_RANK FIRST ORDER BY CASE dsc.desc_type WHEN 'general' THEN 1 WHEN 'location' THEN 2 WHEN 'rooms' THEN 3 WHEN 'lobby' THEN 4 ELSE 5 END) desc_type,
           min(dsc.description) KEEP (DENSE_RANK FIRST ORDER BY CASE dsc.desc_type WHEN 'general' THEN 1 WHEN 'location' THEN 2 WHEN 'rooms' THEN 3 WHEN 'lobby' THEN 4 ELSE 5 END) description
      FROM (SELECT htl.id,
                   htl.city_id,
                   htl.hotel_name,         
                   cty.country_code
              FROM hotel htl
                   LEFT OUTER JOIN city cty
                     ON (htl.city_id = cty.city_id)) dtl
           LEFT OUTER JOIN dsc
             ON (   dtl.id = dsc.id
                AND dtl.city_id = dsc.city_id)
    GROUP BY dtl.id,
             dtl.city_id,
             dtl.hotel_name,
             dtl.country_code,