3

对于所有那些“天哪!他正在使用图像:O:O:O”的人(原始帖子在此之下):

我有一张桌子:

date1 | id1 | value
date1 | id2 | value
date1 | id3 | value
date1 | id4 | value
-------------------
date2 | id1 | value
date2 | id2 | value
date2 | id5 | value
date2 | id7 | value
-------------------
date3 | id4 | value
date3 | id5 | value
date3 | id10 | value
date3 | id11 | value
-------------------
...
-------------------
dateN | id1 | value
dateN | id2 | value
dateN | id3 | value
dateN | id4 | value

输入如下:

date: X - ids: 2, 3
date: Y - ids: 4
date: Z - ids: 2, 4, 5
...

需要一个查询(非 PL、非条件、变量或游标......),它为每个日期和它自己的每个 ID、日期的行和带有特定于它的 VALUE 的 ID 带来。如果日期没有其特定 ID 的值,则必须找到最接近的日期。

IE:

date: 06/03/2016 - ids: 5, 6

结果:

06/03/2016|5|value
04/03/2016|6|value

第二个结果行的日期不同,因为没有找到日期 06/03/2016 和 ID=6 的记录。这就是为什么会带来最接近的匹配日期。哦!,最接近的意思是,之前。不是在日期之后。因此,如果日期不匹配,则指定日期相同或最接近的日期。

我可以为输入的每一行创建一个查询,最后从所有人中创建一个 UNION。但这不是解决问题的优雅方法。并且在每个循环打开 PHP 时抛出查询也不是一种选择。




原线:

早上好,首先,请原谅我的英语,因为我来自西班牙。

说了这么多,最后我会尽量把这个问题简明扼要,但首先,让我暴露环境:

  • 我有一个典型的日期/数据类型/值表。

在此处输入图像描述

  • 我在视觉上用日期更改块的红线划分。蓝色箭头标记“数据类型”ID(来自另一个表)列和另一个蓝色箭头,即与这些值相关联的日期。因此,您拥有具有不同类型 ID 的日期块,对于每个人,您都会获得一个更改值 (CAMBIO):绿色箭头。

现在,¿我能做什么?为我提供某个特定日期的 CAMBIO 值的查询:

在此处输入图像描述

注意:GRUPO 是表中存在的另一列,我总是需要来自这个 grupo 类型的值 1。这是必要的。

下一步是,对于指定的 DATE,表记录上可能不存在值。所以我必须找到最接近的。

我可以做这样的查询:

在此处输入图像描述

您可以在第一张图片上看到没有 3 月 6 日或 3 月 5 日的记录,因此通过此查询,我可以找到最接近的现有值,在本例中为相同的 3 月 4 日。

这些查询的问题是,我需要将 DIVISA_C 列指定为特定值,比如 5 和 10。然后我会仔细检查:

在此处输入图像描述

这对结果中现有的 DIVISA_C id 很有效,但如果我需要一个不包含在“日期块”中的 ID(即:2016-03-04),比如说 6,那么我没有得到任何结果这个DIVISA_C id,我需要有一个结果,具体来说,这是我之前展示的最接近它的日期。

如果我做:

在此处输入图像描述

这 6 个 ID 什么都没有。与上次查询的结果相同。在这种情况下,我也知道如何解决这个问题:

在此处输入图像描述

你看,我在 WHERE 上添加了一个“指针”,从内部查询到 self DIVISA_C id,它基本上指向来自 ourtsider/container 查询的 DIVISA_C。这导致对于内部查询中的指定 DATE,对于容器查询“IN 列表”中的每个 ID,都会按预期带来最可能的关联行。因此,如果内部查询可以解析指定 DIVISA_C id 的指定日期,它会带来记录。否则,为 DIVISA_C id 值带来最接近的日期。这正是我所需要的。

注意:我在内部查询中添加了一些额外的过滤器,以与外部/容器查询保持一致。根本不是要考虑的问题或变化。

现在,解释说,真正的问题来了:

- 现在我有一个日期列表,对于这些日期中的每一个,都有一个 DIVISA_C id 列表。我需要做一个查询,没有 PL-SQL(所以没有 FOR,没有 IF,没有 CURSORS 等),只是一个 SELECT 组合,这给我带来了预期的结果,这基本上是最后一个我已经向您展示了结果,但是很多日期都带有相关的 DIVISA_C ids 列表。

举个例子,我展示的最后一个查询可以解释为:

date: 06/03/2016 - divisa_c ids: 5, 6, 10

在这种情况下,这给我带来了 3 行每个 ID 的近似日期,因为 3 月 6 日没有任何 DIVISA_C id 的记录。

现在我有一个完整的输入列表,只需一个查询即可解决,即:

date: 06/03/2016 - divisa_c ids: 5, 6, 10
date: 05/02/2016 - divisa_c ids: 5
date: 03/02/2016 - divisa_c ids: 5, 6
date: 01/01/2016 - divisa_c ids: 6, 10
date: 31/12/2015 - divisa_c ids: 4, 6, 10, 12
date: 24/10/2015 - divisa_c ids: 3, 4, 5, 11
...

当然,我可以在每个 PHP 循环轮次上针对输入列表的行数进行一次查询。

或者我可以使用列表中的输入行创建每个查询,并将所有这些行合并,以创建一个庞大的长字符串查询,它将准确地给我我需要的结果,但这不是一个选项。 我需要用一种更优雅的方式来解决它,在这里我被困住了...... :(

我虽然有这样的事情:

在此处输入图像描述

您会看到,外部 WHERE 上的某种“链接”数据包导致内部查询为每个关联日期解析 DIVISA_C IN 列表中的所有行,并且在内部查询中,DATE 也是一个指针......但是正如您可以想象的那样,这是行不通的,因为内部查询通过FECHA =(子查询...)链接在where中,并且在此之后我编写的数据包没有意义...

我曾想过在对同一个表的外部查询上创建一个 INNER JOIN,因此表自身以某种方式具有 2 个指针并将它们组合起来以适应这种情况......但我不知道如何正确地做到这一点.. .

你能给我解释一下吗?

谢谢大家,很抱歉这么长的帖子!但我认为通过图像来解释它会更舒服。

问候,

标记。

4

1 回答 1

2

用于row_number()查找最近日期的值。在with子句中定义输入参数,在我的测试数据中我使用了 ('2016-03-04', (5)), ('2016-03-06', (5)), ('2016-03-07', ( 5、6、10))。Id不需要,为了清楚起见,我添加了它:

with t as ( 
  select 1 id, date '2016-03-04' fecha, 5 divisa from dual union all 
  select 2 id, date '2016-03-06' fecha, 5 divisa from dual union all 
  select 3 id, date '2016-03-07' fecha, 5 divisa from dual union all 
  select 3 id, date '2016-03-07' fecha, 6 divisa from dual union all 
  select 3 id, date '2016-03-07' fecha,10 divisa from dual )
select * from (
  select cd.*, t.fecha input_fecha, t.divisa input_divisa,
         row_number() over (partition by t.fecha, t.divisa order by t.fecha-cd.fecha) rn
    from cotizaciones_div cd 
    join t on cd.divisa_c = t.divisa and cd.grupo = 1 and cd.fecha<=t.fecha)
  where rn=1 order by input_fecha, input_divisa

要定义输入参数,您也可以使用 type sys.odcinumberlist,如果它更适合您(当divisa列表很长时,它可以缩短语法),如下所示:

  select 1 id, date '2016-03-04' fecha, column_value as divisa 
    from table(sys.odcinumberlist(5)) union all 
  select 2 id, date '2016-03-06' fecha, column_value as divisa 
    from table(sys.odcinumberlist(5)) union all 
  select 3 id, date '2016-03-07' fecha, column_value as divisa 
    from table(sys.odcinumberlist(5, 6, 10)) 

测试数据和输出:

create table cotizaciones_div (codigo number(8), divisa_o number(3), divisa_c number(3), 
  fecha date, cambio number(12, 4), grupo number(3));

insert into cotizaciones_div values ( 1000,  4, 11, date '2016-01-01', 0.5123, 8);
insert into cotizaciones_div values ( 2273, 15,  6, date '1998-12-31', 0,      1);
insert into cotizaciones_div values (63289,  4,  5, date '2016-03-04', 1.0998, 1);
insert into cotizaciones_div values (63297,  4, 10, date '2016-03-04', 7.4622, 1);
insert into cotizaciones_div values (63290,  4, 11, date '2016-03-04', 0.7738, 1);
insert into cotizaciones_div values (63309,  4,  5, date '2016-03-07', 1.1016, 1);
insert into cotizaciones_div values (63317,  4, 10, date '2016-03-07', 7.4619, 1);
insert into cotizaciones_div values (63310,  4, 11, date '2016-03-07', 0.7724, 1);

   CODIGO DIVISA_O DIVISA_C FECHA               CAMBIO GRUPO INPUT_FECHA INPUT_DIVISA
--------- -------- -------- ----------- -------------- ----- ----------- ------------
    63289        4        5 2016-03-04          1,0998     1 2016-03-04             5
    63289        4        5 2016-03-04          1,0998     1 2016-03-06             5
    63309        4        5 2016-03-07          1,1016     1 2016-03-07             5
     2273       15        6 1998-12-31          0,0000     1 2016-03-07             6
    63317        4       10 2016-03-07          7,4619     1 2016-03-07            10
于 2016-03-08T14:21:48.570 回答