SQL (ORACLE): 内部查询有 2 个或更多 related/paired 容器查询 "pointers"
SQL (ORACLE): inner-query with 2 or more related/paired container-query "pointers"
对于所有 "OMG! HE IS USING IMAGES :O :O :O" 人(原始 POST 在此之下):
我有一个 table:
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 的值,则必须找到最近的日期。
即:
date: 06/03/2016 - ids: 5, 6
结果:
06/03/2016|5|value
04/03/2016|6|value
第二个结果行有不同的日期,因为没有找到日期为 06/03/2016 且 ID=6 的记录。这就是为什么带来最接近的匹配日期。哦!,最接近我的意思是,之前。不在日期之后。因此,如果日期不匹配,则指定相同的指定日期或最近的日期。
我可以为输入的每一行创建一个查询,最后从所有行中创建一个 UNION。但这不是解决它的优雅方法。并且在每个循环打开时抛出查询 PHP 也不是一个选项。
原帖:
早上好,首先请原谅我的英语不好,因为我来自西班牙。
说到这里,我会在最后尽量简洁地回答这个问题,但首先让我暴露一下环境:
- 我有一个典型的 date/data-type/value table.
- 我用日期更改块的红线在视觉上进行了划分。蓝色箭头标记 "data-type" ID(来自另一个 table)列,另一个蓝色箭头标记与这些值相关的日期。
因此,您拥有具有不同类型 ID 的日期块,其中每个日期块都有一个更改值 (CAMBIO):绿色箭头。
现在,我能做什么?为我提供某个特定日期的 CAMBIO 值的查询:
注意:GRUPO 是存在于table 上的另一个列,我总是需要来自这个grupo-type 的值,1。这是必要的。
下一步是,对于指定的日期,table 记录中可能不存在值。所以我必须找到最近的一个。
我可以这样查询:
您可以在第一张图片上看到没有 3 月 6 日或 3 月 5 日的记录,因此通过此查询,我可以找到最接近的现有值,在本例中为同一个 3 月 4 日。
这些查询的问题是,我需要将 DIVISA_C 列指定为特定值,比方说 5 和 10。然后我通过这个:
这对结果中现有的 DIVISA_C id 很有效,但是如果我需要一个不包含在 "date-block" 中的 ID(即:2016-03-04),让我们说6,然后我没有得到这个 DIVISA_C id 的结果,并且 我需要 得到它的结果,具体地说,就是我所展示的最接近的日期之前。
如果我这样做:
这个 6 ID 没有任何结果。与上次查询相同的结果。
这样的话,我也知道怎么解决了:
你看,我在内部查询到自身 DIVISA_C id 的 WHERE 上添加了一个 "pointer",它基本上指向 DIVISA_C 来自 [=146] =]查询。这导致对于内部查询的指定日期,对于容器查询 "IN list" 中的每个 ID,都会按预期带来最可能的关联行。因此,如果内部查询可以为指定的 DIVISA_C id 解析指定的日期,它会带来记录。否则,为 DIVISA_C id 值带来最接近的日期。这正是我所需要的。
注意: 我在内部查询中添加了一些额外的过滤器以与 outside/container 查询保持一致。根本不是问题或需要考虑的变化。
现在,解释一下,真正的问题来了:
- 现在我有一个日期列表,对于每个日期,都有一个 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 上的某种 "linked" 数据包,导致内部查询为每个关联日期和内部查询解析 DIVISA_C IN 列表中的所有行,DATE 也是一个指针......但是你可以想象这不起作用,因为内部查询通过 FECHA =(子查询......)链接在 where 中,并且没有意义的数据包我在此之后写道...
我想在外部查询上创建一个 INNER JOIN 到完全相同的 table,因此 table 以某种方式针对自身有 2 个指针并将它们组合起来以适应这种情况...但我不知道如何正确地做...
你能给我解释一下吗?
感谢大家,抱歉这么久post!不过我觉得用图片来解释更符合table
你好,
马克.
使用 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
要定义输入参数,您也可以使用 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
对于所有 "OMG! HE IS USING IMAGES :O :O :O" 人(原始 POST 在此之下):
我有一个 table:
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 的值,则必须找到最近的日期。
即:
date: 06/03/2016 - ids: 5, 6
结果:
06/03/2016|5|value
04/03/2016|6|value
第二个结果行有不同的日期,因为没有找到日期为 06/03/2016 且 ID=6 的记录。这就是为什么带来最接近的匹配日期。哦!,最接近我的意思是,之前。不在日期之后。因此,如果日期不匹配,则指定相同的指定日期或最近的日期。
我可以为输入的每一行创建一个查询,最后从所有行中创建一个 UNION。但这不是解决它的优雅方法。并且在每个循环打开时抛出查询 PHP 也不是一个选项。
原帖:
早上好,首先请原谅我的英语不好,因为我来自西班牙。
说到这里,我会在最后尽量简洁地回答这个问题,但首先让我暴露一下环境:
- 我有一个典型的 date/data-type/value table.
- 我用日期更改块的红线在视觉上进行了划分。蓝色箭头标记 "data-type" ID(来自另一个 table)列,另一个蓝色箭头标记与这些值相关的日期。 因此,您拥有具有不同类型 ID 的日期块,其中每个日期块都有一个更改值 (CAMBIO):绿色箭头。
现在,我能做什么?为我提供某个特定日期的 CAMBIO 值的查询:
注意:GRUPO 是存在于table 上的另一个列,我总是需要来自这个grupo-type 的值,1。这是必要的。
下一步是,对于指定的日期,table 记录中可能不存在值。所以我必须找到最近的一个。
我可以这样查询:
您可以在第一张图片上看到没有 3 月 6 日或 3 月 5 日的记录,因此通过此查询,我可以找到最接近的现有值,在本例中为同一个 3 月 4 日。
这些查询的问题是,我需要将 DIVISA_C 列指定为特定值,比方说 5 和 10。然后我通过这个:
这对结果中现有的 DIVISA_C id 很有效,但是如果我需要一个不包含在 "date-block" 中的 ID(即:2016-03-04),让我们说6,然后我没有得到这个 DIVISA_C id 的结果,并且 我需要 得到它的结果,具体地说,就是我所展示的最接近的日期之前。
如果我这样做:
这个 6 ID 没有任何结果。与上次查询相同的结果。 这样的话,我也知道怎么解决了:
你看,我在内部查询到自身 DIVISA_C id 的 WHERE 上添加了一个 "pointer",它基本上指向 DIVISA_C 来自 [=146] =]查询。这导致对于内部查询的指定日期,对于容器查询 "IN list" 中的每个 ID,都会按预期带来最可能的关联行。因此,如果内部查询可以为指定的 DIVISA_C id 解析指定的日期,它会带来记录。否则,为 DIVISA_C id 值带来最接近的日期。这正是我所需要的。
注意: 我在内部查询中添加了一些额外的过滤器以与 outside/container 查询保持一致。根本不是问题或需要考虑的变化。
现在,解释一下,真正的问题来了:
- 现在我有一个日期列表,对于每个日期,都有一个 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 上的某种 "linked" 数据包,导致内部查询为每个关联日期和内部查询解析 DIVISA_C IN 列表中的所有行,DATE 也是一个指针......但是你可以想象这不起作用,因为内部查询通过 FECHA =(子查询......)链接在 where 中,并且没有意义的数据包我在此之后写道...
我想在外部查询上创建一个 INNER JOIN 到完全相同的 table,因此 table 以某种方式针对自身有 2 个指针并将它们组合起来以适应这种情况...但我不知道如何正确地做...
你能给我解释一下吗?
感谢大家,抱歉这么久post!不过我觉得用图片来解释更符合table
你好,
马克.
使用 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
要定义输入参数,您也可以使用 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