Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL-组合不完全_Sql_Oracle - Fatal编程技术网

SQL-组合不完全

SQL-组合不完全,sql,oracle,Sql,Oracle,我正在使用Oracle 10g。我有一个表,其中有许多不同类型的字段。这些字段包含特定站点在特定日期对特定事物所做的观察 因此: 每个记录中大约有40次观察。此时无法更改表结构 不幸的是,并不是所有的观测结果都被填充(要么是偶然的,要么是因为站点无法进行记录)。我需要在一个查询中将关于特定项的所有记录合并到一个记录中,使其尽可能完整 一个简单的方法是 SELECT ItemID, MAX(Date), MAX(Observation1), MAX(Observat

我正在使用Oracle 10g。我有一个表,其中有许多不同类型的字段。这些字段包含特定站点在特定日期对特定事物所做的观察

因此:

每个记录中大约有40次观察。此时无法更改表结构

不幸的是,并不是所有的观测结果都被填充(要么是偶然的,要么是因为站点无法进行记录)。我需要在一个查询中将关于特定项的所有记录合并到一个记录中,使其尽可能完整

一个简单的方法是

SELECT
    ItemID,
    MAX(Date),
    MAX(Observation1),
    MAX(Observation2)
    etc.
FROM
    Table
GROUP BY
    ItemID
但理想情况下,我希望它选择可用的最新观测值,而不是最大/最小值。我可以通过在表单中编写子查询来实现这一点

SELECT
    ItemID,
    ObservationX,
    ROW_NUMBER() OVER (PARTITION BY ItemID ORDER BY Date DESC) ROWNUMBER
FROM
    Table
WHERE
    ObservationX IS NOT NULL
并将所有行数1合并为一个ItemID,但由于字段的数量,这将需要40个子查询


我的问题是,是否有一种更简洁的方法可以做到这一点,但我没有。

创建表格和示例日期

SQL> create table observation(
  2    item_id number,
  3    dt      date,
  4    val1    number,
  5    val2    number );

Table created.

SQL> insert into observation values( 1, date '2011-12-01', 1, null );

1 row created.

SQL> insert into observation values( 1, date '2011-12-02', null, 2 );

1 row created.

SQL> insert into observation values( 1, date '2011-12-03', 3, null );

1 row created.

SQL> insert into observation values( 2, date '2011-12-01', 4, null );

1 row created.

SQL> insert into observation values( 2, date '2011-12-02', 5, 6 );

1 row created.
然后使用
MAX
聚合函数上的
KEEP
子句,使用
orderby
将观察值为空的行放在末尾。您在ORDER BY中使用的任何日期都必须早于表中最早的实际观测值

SQL> ed
Wrote file afiedt.buf

  1  select item_id,
  2         max(val1) keep( dense_rank last
  3                              order by (case when val1 is not null
  4                                             then dt
  5                                             else date '1900-01-01'
  6                                          end) ) val1,
  7         max(val2) keep( dense_rank last
  8                              order by (case when val2 is not null
  9                                             then dt
 10                                             else date '1900-01-01'
 11                                          end) ) val2
 12    from observation
 13*  group by item_id
SQL> /

   ITEM_ID       VAL1       VAL2
---------- ---------- ----------
         1          3          2
         2          5          6

我怀疑有一种更优雅的方法可以忽略空值,而不是将
CASE
语句添加到
ORDER BY
中,但是
CASE
可以完成任务。

我不知道oracle中的命令,但在sql中,您可以使用一些方法来实现这一点

第一个使用透视表是包含连续数字0,1,2

我不确定,但在oracle中,函数“isnull”是“NVL”

pivot表的概念可以在“Transact-SQL Cookbook By Jonathan Gennick,Ales Spetic”中查阅

我必须承认,上述解决方案(由Justin Cave提出)更简单、更容易理解,但这是另一个好的选择


最后就像你说的,你解决了

+1,很好。你能不能不通过NVL2(val1,dt,日期'1900-01-01')订购更紧凑的解决方案?@DCookie-那会更紧凑,是的。但是当我看到
NVL2
时,我总是会停下来,因为我从来都不记得它是干什么的。我希望在聚合函数中有类似于
last_value
分析函数的
ignorenulls
子句的东西。
SQL> ed
Wrote file afiedt.buf

  1  select item_id,
  2         max(val1) keep( dense_rank last
  3                              order by (case when val1 is not null
  4                                             then dt
  5                                             else date '1900-01-01'
  6                                          end) ) val1,
  7         max(val2) keep( dense_rank last
  8                              order by (case when val2 is not null
  9                                             then dt
 10                                             else date '1900-01-01'
 11                                          end) ) val2
 12    from observation
 13*  group by item_id
SQL> /

   ITEM_ID       VAL1       VAL2
---------- ---------- ----------
         1          3          2
         2          5          6
  select items.ItemId,
    case p.i = 0 then observation1 else '' end as observation1,
    case p.i = 0 then observation1 else '' end as observation2,
    case p.i = 0 then observation1 else '' end as observation3,
    ...
    case p.i = 39 then observation4 else '' as observation40
  from (
    select items.ItemId
    from table as items
    where items.item = _paramerter_for_retrive_only_one_item /* select one item o more item where you filter items here*/
    group by items.ItemId) itemgroup
    left join 
    (
      select 
       items.ItemId, 
       p.i,
       isnull(    max  (  case p.i = 0 then observation1 else '' end ), '' ) as observation1,
       isnull(    max  (  case p.i = 1 then observation2 else '' end ), '' ) as observation2,
       isnull(    max  (  case p.i = 2 then observation3 else '' end), '' ) as observation3,
       ...
       isnull(    max  (  case p.i = 39 then observation4), '' ) as observation40,
      from 
       (select i from pivot where id < 40 /*you number of columns of observations, that attach one index*/
       )
       as p
       cross join table as items

       lef join table as itemcombinations
       on item.itemid = itemcombinations.itemid

       where items.item = _paramerter_for_retrive_only_one_item /* select one item o more item where you filter items here*/
        and (p.i = 0 and not itemcombinations.observation1 is null) /* column 1 */
        and (p.i = 1 and not itemcombinations.observation2 is null) /* column 2 */
        and (p.i = 2 and not itemcombinations.observation3 is null) /* column 3 */
        .... 
        and (p.i = 39 and not itemcombinations.observation3 is null) /* column 39 */
       group by p.i, items.ItemId
     ) as itemsimplified
     on itemsimplified.ItemId = itemgroup.itemId

  group by itemgroup.itemId
create foo table

schema foo

name: foo column: value datatype varchar

insert into foo
values('0'),
values('1'),
values('2'),
values('3'),
values('4'),
values('5'),
values('6'),
values('7'),
values('8'),
values('9');

/* insert 100 values */
insert into pivot
select concat(a.value, a.value) /* mysql */
   a.value + a.value /* sql server */
   a.value | a.value /* Oracle im not sure about that sintax */
from foo a, foo b

/* insert 1000 values */
insert into pivot
select concat(a.value, b.value, c.value) /* mysql  */
a.value + b.value + c.value /* sql server */
a.value | b.value | c.value /* Oracle im not sure about that sintax */
from foo a, foo b, foo c