【问题标题】:Oracle SQL Query with joining four tables to get only one row of multiple entries连接四个表以仅获取一行多个条目的 Oracle SQL 查询
【发布时间】:2015-05-23 13:00:44
【问题描述】:

我的桌子是这样设置的:

Table 1            Table 2                            Table 3        
+-------+-----+    +-------+-------+-------+-----+    +-------+-----+
| ID    | ... |    | ID    | T1_ID | T3_ID | ... |    | ID    | ... |
+-------+-----+    +-------+-------|-------|-----|    |-------|-----|
|  101  | ... |    |  202  |  101  |  301  | ... |    |  300  | ... |
|  102  | ... |    |  203  |  101  |  302  | ... |    |  302  | ... |
|  104  | ... |    |  204  |  101  |  302  | ... |    |  314  | ... |
+-------+-----+    |  205  |  101  |  302  | ... |    +-------+-----+
                   |  206  |  104  |  327  | ... |                   
                   +-------+-------+-------+-----+                   

我想构造一个子查询语句,如果 table2.t3_id 存在于表 3 中,则只为表 1 的给定 id 选择表 2 的一行

重要的是,表2中可能存在多行具有相同t3_id的行。因此,表2和表之间的外键关系不是唯一的或根本不存在。

我的想法是以下陈述:

inner join 
(
    SELECT * 
    FROM (
        SELECT t3_id, t1_id, id 
        FROM table2 
        WHERE EXISTS 
        (
            SELECT id 
            FROM table3
        )
    ) 
    WHERE ROWNUM=1
) tb2 ON tb1.id = tb2.t1_id

这个语句返回多行,但我只需要一个。 我该怎么做?

【问题讨论】:

  • 结果应该是?如果存在多行,取哪一行?
  • 如果存在多行,取哪一行都没有关系。你可以拿第一个。结果应该是表 2 中的 id 或其用于连接的行。
  • 您实际需要哪些列?你有什么理由不能做SELECT t1_id, MAX(t3_id) FROM Table2 JOIN Table3 ON Table3.id = Table2.t3_id GROUP BY t1_id之类的事情吗?为什么Table3 中有缺失值?拥有空的部分键通常是一个坏主意(您的数据库/应用程序设计似乎有些麻烦,匿名)。

标签: sql database oracle join


【解决方案1】:

未经测试,但应该做你需要的

SELECT *
FROM table1 t1 JOIN table2 t2 
ON ( t1.id = t2.t1_id
     AND EXISTS ( SELECT 'x'
                  FROM table3 t3
                  WHERE t2.t3_id = t3.id
                 )
     AND NOT EXISTS ( SELECT 'a'
                      FROM table2 t22 
                      WHERE t22.t1_id = t2.t1_id
                      AND t22.id < t2.id
                     )
   )

【讨论】:

    【解决方案2】:

    您可以通过使用row_number() 枚举它们然后只选择一个值来获取一行多个条目。这是一个例子:

    select . . .
    from table1 t1 join
         (select t2.*, row_number() over (partition by t.id order by t2.id) as seqnum
          from table2 t2
         ) t2
         on t2.t1_id = t1.id and t2.seqnum = 1;
    

    编辑:

    对于所有三个表,您要进行 row_number() 所有连接:

    select . . .
    from (select . . ., row_number() over (partition by t1_id order by id) as seqnum
          from table1 t1 join
               table2 t2
               on t2.t1_id = t1.id join
               table3 t3
               on t2.t3_id = t3.id
         ) t
    where seqnum = 1;
    

    【讨论】:

    • 感谢您的回答。我已经尝试过这种方法。但我无法涉及所有三个表的关系。我可以更详细地展示您的示例吗?
    • 对所有关系执行此操作是否会比将连接移动到Table1 更高级别造成更大的惩罚? t1_id 将是唯一的,因为它是分区,所以...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多