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

Is there a way to reuse subqueries in the same query?

请参阅问题末尾的更新以获取解决方案,感谢标记的答案!

我想将子查询视为可以在同一查询中重复使用的实际 table。这是设置 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);

我想要做的是 return 只有 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

它returns:

+----+---------------------------------+----------------------------+
| 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 |
+----+---------------------------------+----------------------------+

下一步是 return 每个 ID 仅最后一行。如果我要使用这个 SQL 将之前的 SELECT 写入 table...

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

它将return这样:

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

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

更新

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

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

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;