我试图每个记录返回一行,但我收到多个

时间:2014-12-15 18:29:24

标签: sql oracle plsql

我正在尝试查询表格。该表包含条形码和与条形码相关的活动,特别是在移动条形码时和其中。我正在尝试为每个条形码返回一条记录,其中包含与位置一起移动的最后日期和时间。我目前有MAX围绕移动日期和时间。以下是重复行的示例。

BarCode       Location  Date           Time
000055279 1   EWC       03-APR-14      12:30:44  
000055279 1   G-T       05-AUG-14      08:16:10  
000055279 1   TBD       20-AUG-14      08:32:14

我只想要此示例中的最后一行(000055279 1 TBD 20-AUG-14 08:32:14)。目前的查询基本上是:

SELECT DISTINCT "BarCode", "Location", MAX("Date"), MAX("Time")
FROM TABLE1

一旦我添加了位置,就会发生重复。

提前致谢。

3 个答案:

答案 0 :(得分:3)

有几种选择。一种是使用row_number()

select *
from (
    select barcode, location, date, time, 
           row_number() over (partition by barcode order by date desc, time desc) rn
    from table1
) t
where rn = 1

答案 1 :(得分:2)

根据您的想法,但修复设计中的缺陷,您可以(重新)使用CTE生成正确的 datetime 列,然后查询该视图:

WITH V AS (SELECT "BarCode", "Location",
                  TO_DATE("Date"|| ' ' || "Time", 'DD-MON-YY HH:MI:SS') "datetime"
           FROM TABLE1)


SELECT "BarCode", "Location", MAX("datetime")
FROM V
GROUP BY "BarCode", "Location"
     

未测试。小心拼写错误!


话虽如此,但就我自己而言,我会推动表格中只有一个DATE列。如果由于某种原因不可行,也许您可​​以建议添加虚拟列:

ALTER TABLE TABLE1
ADD ("datetime" DATE GENERATED ALWAYS 
             AS (TO_DATE("Date"|| ' ' || "Time", 'DD-MON-YY HH:MI:SS')) VIRTUAL);

答案 2 :(得分:0)

Oracle ROW_NUMBER分析功能是您所需要的。 Oracle documentation解释得很好,这是一个有用的例子,使用你的数据和一些额外的条形码来说明它在更现实的数据集中工作。我正在连接日期&时间列并使用TO_DATE获取正确的日期。由于这些是保留字,因此用双引号括起来。

SQL> create table barcode_activity (
  2  barcode varchar2(20),
  3  location varchar2(10),
  4  "date"  varchar2(10),
  5  "time"  varchar2(10)
  6  );

Table created.

SQL> 
SQL> insert into barcode_activity
  2  values
  3  ( '000055279 1','EWC', '03-APR-14','12:30:44')
  4  
SQL> insert into barcode_activity
  2  values
  3  ( '000055279 1','G-T', '05-APR-14','08:16:10');

1 row created.

SQL> 
SQL> insert into barcode_activity
  2  values
  3  ( '000055279 1','TBD', '20-APR-14', '08:32:14');

1 row created.

SQL> 
SQL> insert into barcode_activity
  2  values
  3  ( '000009999 1','TBD', '20-APR-14', '07:42:32');

1 row created.

SQL> 
SQL> insert into barcode_activity
  2  values
  3  ( '000001234 1','TBD', '29-APR-14', '17:22:18');

1 row created.

SQL> 
SQL> insert into barcode_activity
  2  values
  3  ( '000001234 1','TBD', '29-APR-14', '17:22:18');

1 row created.

SQL> 
SQL> insert into barcode_activity
  2  values
  3  ( '000001234 1','TBD', '29-APR-14', '17:22:18');

1 row created.

SQL> commit;

Commit complete.

SQL> 
SQL> SELECT * FROM barcode_activity ORDER BY 1,2,3;

BARCODE          LOCATION   date       time
-------------------- ---------- ---------- ----------
000001234 1      TBD    29-APR-14  17:22:18
000001234 1      TBD    29-APR-14  17:22:18
000001234 1      TBD    29-APR-14  17:22:18
000009999 1      TBD    20-APR-14  07:42:32
000055279 1      G-T    05-APR-14  08:16:10
000055279 1      TBD    20-APR-14  08:32:14

6 rows selected.

SQL> 
SQL> /* rank solution
SQL>    this will return one row
SQL>    for all barcodes in the table where there are collisions in rank th
SQL>    multiple rows are returned 
SQL>   */
SQL> SELECT barcode, location, "date", "time"
  2  FROM
  3          (SELECT barcode,
  4              location,
  5              "date",
  6              "time",
  7              RANK() OVER (
  8                PARTITION BY barcode
  9                ORDER BY TO_DATE("date"||' '||"time",'DD-MON-YYYY HH24:MI:SS') DESC
 10                ) AS activity_order
 11          FROM barcode_activity)
 12  WHERE activity_order = 1;

BARCODE          LOCATION   date       time
-------------------- ---------- ---------- ----------
000001234 1      TBD    29-APR-14  17:22:18
000001234 1      TBD    29-APR-14  17:22:18
000001234 1      TBD    29-APR-14  17:22:18
000009999 1      TBD    20-APR-14  07:42:32
000055279 1      TBD    20-APR-14  08:32:14

SQL> 
SQL> /* row_number solution - works regardless of collisions    */
SQL> SELECT barcode, location, "date", "time"
  2  FROM
  3          (SELECT barcode,
  4              location,
  5              "date",
  6              "time",
  7              row_number() OVER (
  8                PARTITION BY barcode
  9                ORDER BY TO_DATE("date"||' '||"time",'DD-MON-YYYY HH24:MI:SS') DESC
 10                ) AS activity_order
 11          FROM barcode_activity)
 12  WHERE activity_order = 1;

BARCODE          LOCATION   date       time
-------------------- ---------- ---------- ----------
000001234 1      TBD    29-APR-14  17:22:18
000009999 1      TBD    20-APR-14  07:42:32
000055279 1      TBD    20-APR-14  08:32:14