如何仅选择第一行?

时间:2019-05-24 16:13:21

标签: sql oracle

我有这张桌子

Table_A

  link    name
  1       toto 
  2       lulu

Table_B

  link    action   date
  1       OK       01/02/2010 
  1       OK       01/02/2022
  1       OK       01/03/2021
  1       OK       01/02/2025

然后我想查询

Select 
  * 
from 
  Table_A, Table_B 
where
  table_A.link (+)= table_b.link and
  table_b.action (+)= 'OK' 

问题在于此查询返回重复项

link    name    action    date
1       toto    OK        01/02/2010 
1       toto    OK        01/02/2022
1       toto    OK        01/03/2021
1       toto    OK        01/02/2025
2       lulu

我想要:

link    name    action    date
1       toto    OK        01/02/2025
2       lulu

怎么办?

5 个答案:

答案 0 :(得分:1)

通常最好使用ANSI连接语法,但是按照您的指导,我将使用Oracle语法(对于外部连接使用“ plus”运算符)。

首先,请注意,在WHERE子句的第一个条件中,您的“ +”在错误的一侧;您需要将“虚拟”行添加到table_B,而不是table_A

然后,如果仅依赖一个表,通常最好先进行聚合。这是我在下面FROM子句中的子查询中所做的。

此外,date是Oracle的关键字,不应用作列名。希望您不要那样使用它。对于我的代码,我假设列名称为dt

select a.link, a.name, b.action, b.dt
from   table_a a,
       ( select link, 'OK' action, max(dt) dt
         from   table_b
         where  action = 'OK'
         group  by link
       ) b
where  b.link (+) = a.link
;

答案 1 :(得分:0)

您可以使用Distinct语句:documentation选择唯一数据。

另外,请检查Group By语句:https://www.techonthenet.com/oracle/distinct.php以按某些列分组,例如选择唯一的名称:

Select 
  * 
from 
  Table_A, Table_B 
where
  table_A.link (+)= table_b.link and
  table_b.action (+)= 'OK'
group by table_A.name

答案 2 :(得分:0)

您可以使用row_number()窗口分析功能

Select link, name, action, "date"
  From
  (
   Select a.link, a.name, b.action, b."date",
          row_number() over (partition by a.link order by b."date" desc ) as rn
     From Table_A a
     Left Join Table_B b 
       on a.link = b.link
      and b.action = 'OK' 
  )
  Where rn = 1;

LINK  NAME  ACTION  date
----  ----- ------  ----------
1     toto  OK      01.02.2025
2     lulu  NULL    NULL

Demo

P.S。显然,我不建议使用旧的逗号分隔的联接语法,而我像上面的查询中那样使用ANSI-92 SQL语法。另一个要点是,Oracle DB的SQL不需要子查询的别名,但是其他大多数DBMS都需要别名。

答案 3 :(得分:0)

使用正确,明确,标准 Select a.*, b.* from Table_A a left join (select b.*, row_number() over (partition by b.link order by b.date desc) as seqnum from Table_B b where b.action = 'OK' ) b on b.link = a.link and b.seqnum = 1; 语法!

编写查询的简单方法:

Select a.link, a.name, b.action, max(b.date)
from Table_A a left join
     Table_B b
     on b.link = a.link and b.action = 'OK'
group by a.link, a.name, b.action

或使用聚合:

 $list=Get-PnpDevice | Sort-Object -Property Name | Where-Object -Property ConfigurationFlags -NotLike '*DISABLED*' | ft Name, InstanceId -AutoSize

答案 4 :(得分:0)

1)使用关键字GROUP BY

https://www.techonthenet.com/oracle/group_by.php

2)对于日期,好的做法是使用格式:YYYY-MM-dd

link action date
1    OK     2010-02-01

用于显示:

link name action date
1    toto OK     2025-02-01
2    lulu        2023-03-01

在表_b中插入露露条目

我的Table_b:

link  action  date
1     OK      2010-02-01
1     OK      2022-02-01
1     OK      2021-03-01
1     OK      2025-02-01
2             2023-03-01

3)尝试以下查询(MySQL语法):

SELECT 
  Table_A.link, Table_a.name, action, MAX(date) AS date
FROM 
  Table_A, Table_B 
WHERE
  Table_A.link = Table_B.link
  GROUP BY name
  ORDER BY link;