有没有办法在同一个查询中重用子查询?

时间:2015-05-06 14:41:37

标签: teradata

通过明确的答案,请在问题结尾处查看更新以获得解决方案!

我想将子查询视为可以在同一查询中重用的实际表。这是设置SQL:

create table mydb.mytable
(
    id integer not null,
    fieldvalue varchar(100),
    ts timestamp(6) not null
)
unique primary index (id, ts)

insert into mydb.mytable(0,'hello',current_timestamp - interval '1' minute);
insert into mydb.mytable(0,'hello',current_timestamp - interval '2' minute);
insert into mydb.mytable(0,'hello there',current_timestamp - interval '3' minute);
insert into mydb.mytable(0,'hello there, sir',current_timestamp - interval '4' minute);
insert into mydb.mytable(0,'hello there, sir',current_timestamp - interval '5' minute);
insert into mydb.mytable(0,'hello there, sir.  how are you?',current_timestamp - interval '6' minute);

insert into mydb.mytable(1,'what up',current_timestamp - interval '1' minute);
insert into mydb.mytable(1,'what up',current_timestamp - interval '2' minute);
insert into mydb.mytable(1,'what up, mr man?',current_timestamp - interval '3' minute);
insert into mydb.mytable(1,'what up, duder?',current_timestamp - interval '4' minute);
insert into mydb.mytable(1,'what up, duder?',current_timestamp - interval '5' minute);
insert into mydb.mytable(1,'what up, duder?',current_timestamp - interval '6' minute);

我想要做的只是返回FieldValue与前一行不同的行。这个SQL就是这样做的:

locking row for access
select id, fieldvalue, ts from 
(
    --locking row for access
    select
        id, fieldvalue, 
        min(fieldvalue) over 
        (
            partition by id 
            order by ts, fieldvalue rows 
            between 1 preceding and 1 preceding
        ) fieldvalue2,
        ts
    from mydb.mytable
) x
where
    hashrow(fieldvalue) <> hashrow(fieldvalue2)
order by id, ts desc

它返回:

+----+---------------------------------+----------------------------+
| id |           fieldvalue            |             ts             |
+----+---------------------------------+----------------------------+
|  0 | hello                           | 2015-05-06 10:13:34.160000 |
|  0 | hello there                     | 2015-05-06 10:12:34.350000 |
|  0 | hello there, sir                | 2015-05-06 10:10:34.750000 |
|  0 | hello there, sir.  how are you? | 2015-05-06 10:09:34.970000 |
|  1 | what up                         | 2015-05-06 10:13:35.470000 |
|  1 | what up, mr man?                | 2015-05-06 10:12:35.690000 |
|  1 | what up, duder?                 | 2015-05-06 10:09:36.240000 |
+----+---------------------------------+----------------------------+

下一步是仅返回每个ID的最后一行。如果我使用这个SQL将前一个SELECT写入表...

create table mydb.reusetest as (above sql) with data;

...我可以这样做,每个ID获取最后一行:

locking row for access
select t1.* from mydb.reusetest t1,
(
    select id, max(ts) ts from mydb.reusetest
    group by id
) t2
where
    t2.id = t1.id and
    t2.ts = t1.ts
order by t1.id

它会返回:

+----+------------+----------------------------+
| id | fieldvalue |             ts             |
+----+------------+----------------------------+
|  0 | hello      | 2015-05-06 10:13:34.160000 |
|  1 | what up    | 2015-05-06 10:13:35.470000 |
+----+------------+----------------------------+

如果我可以在初始SELECT中重用子查询,我可以获得相同的结果。我可以将整个查询SQL复制/粘贴到另一个子查询中以创建派生表,但这只是意味着如果我需要修改它,我需要在两个地方更改SQL。

更新

感谢Kristján,我能够将WITH子句实现到我的SQL中,以获得完美的结果:

locking row for access
with items (id, fieldvalue, ts) as
(
    select id, fieldvalue, ts from 
    (
        select
            id, fieldvalue, 
            min(fieldvalue) over 
            (
                partition by id
                order by ts, fieldvalue
                rows between 1 preceding and 1 preceding
            ) fieldvalue2,
            ts
        from mydb.mytable
    ) x
    where
        hashrow(fieldvalue) <> hashrow(fieldvalue2)
)
select t1.* from items t1,
(
    select id, max(ts) ts from items
    group by id
) t2
where
    t2.id = t1.id and
    t2.ts = t1.ts
order by t1.id

1 个答案:

答案 0 :(得分:1)

WITH有帮助吗?这使您可以定义一个可以在SELECT中多次使用的结果集。

从他们的例子:

WITH orderable_items (product_id, quantity) AS
 ( SELECT stocked.product_id, stocked.quantity
   FROM stocked, product
   WHERE stocked.product_id = product.product_id
   AND   product.on_hand > 5
 )

SELECT product_id, quantity
FROM orderable_items
WHERE quantity < 10;