更新 SELECT 查询中的列值
Update a column value within a SELECT query
我有一个复杂的 SQL 问题。
我们可以更新 SELECT 查询中的列吗?示例:
考虑这个 table:
|ID |SeenAt |
----------------
|1 |20 |
|1 |21 |
|1 |22 |
|2 |70 |
|2 |80 |
我想要一个 SELECT 查询,为每个 ID 提供首次看到的时间。什么时候看到的 'again':
|ID |Start |End |
---------------------
|1 |20 |21 |
|1 |20 |22 |
|1 |20 |22 |
|2 |70 |80 |
|2 |70 |80 |
首先,Start
和 End
两列都具有相同的值,但是当看到具有相同 ID
的第二行时,我们需要更新其前身以提供 End
新的 SeenAt
值。
我成功创建了 Start
列,我将每个 ID
的最小值 SeenAt
赋予所有 ID。但是我找不到每次都更新 End
列的方法。
不要介意双打,我还有其他列在每个新行中都会发生变化
此外,我在 Impala 工作,但我可以使用 Oracle。
我希望我已经足够清楚了。谢谢
开始很容易只是 MIN
的 GROUP
结束你需要在 SeenAt
之后找到 MIN,如果你没有找到它那么当前的 SeenAt
SELECT "ID",
(SELECT MIN("SeenAt")
FROM Table1 t2
WHERE t1."ID" = t2."ID") as "Start",
COALESCE(
(SELECT MIN("SeenAt")
FROM Table1 t2
WHERE t1."ID" = t2."ID"
AND t1."SeenAt" < t2."SeenAt")
, t1."SeenAt"
) as End
FROM Table1 t1
输出
| ID | START | END |
|----|-------|-----|
| 1 | 20 | 21 |
| 1 | 20 | 22 |
| 1 | 20 | 22 |
| 2 | 70 | 80 |
| 2 | 70 | 80 |
您似乎需要 min()
具有 self-join
:
的分析函数
select distinct t1.ID,
min(t1.SeenAt) over (partition by t1.ID order by t1.ID) as "Start",
t2.SeenAt as "End"
from tab t1
join tab t2 on t1.ID=t2.ID and t1.SeenAt<=t2.SeenAt
order by t2.SeenAt;
您可以使用 lead()
和 nvl()
:
select id, min(seenat) over (partition by id) seen_start,
nvl(lead(seenat) over (partition by id order by seenat), seenat) seen_end
from t
我有一个复杂的 SQL 问题。
我们可以更新 SELECT 查询中的列吗?示例:
考虑这个 table:
|ID |SeenAt |
----------------
|1 |20 |
|1 |21 |
|1 |22 |
|2 |70 |
|2 |80 |
我想要一个 SELECT 查询,为每个 ID 提供首次看到的时间。什么时候看到的 'again':
|ID |Start |End |
---------------------
|1 |20 |21 |
|1 |20 |22 |
|1 |20 |22 |
|2 |70 |80 |
|2 |70 |80 |
首先,Start
和 End
两列都具有相同的值,但是当看到具有相同 ID
的第二行时,我们需要更新其前身以提供 End
新的 SeenAt
值。
我成功创建了 Start
列,我将每个 ID
的最小值 SeenAt
赋予所有 ID。但是我找不到每次都更新 End
列的方法。
不要介意双打,我还有其他列在每个新行中都会发生变化
此外,我在 Impala 工作,但我可以使用 Oracle。
我希望我已经足够清楚了。谢谢
开始很容易只是 MIN
的 GROUP
结束你需要在 SeenAt
之后找到 MIN,如果你没有找到它那么当前的 SeenAt
SELECT "ID",
(SELECT MIN("SeenAt")
FROM Table1 t2
WHERE t1."ID" = t2."ID") as "Start",
COALESCE(
(SELECT MIN("SeenAt")
FROM Table1 t2
WHERE t1."ID" = t2."ID"
AND t1."SeenAt" < t2."SeenAt")
, t1."SeenAt"
) as End
FROM Table1 t1
输出
| ID | START | END |
|----|-------|-----|
| 1 | 20 | 21 |
| 1 | 20 | 22 |
| 1 | 20 | 22 |
| 2 | 70 | 80 |
| 2 | 70 | 80 |
您似乎需要 min()
具有 self-join
:
select distinct t1.ID,
min(t1.SeenAt) over (partition by t1.ID order by t1.ID) as "Start",
t2.SeenAt as "End"
from tab t1
join tab t2 on t1.ID=t2.ID and t1.SeenAt<=t2.SeenAt
order by t2.SeenAt;
您可以使用 lead()
和 nvl()
:
select id, min(seenat) over (partition by id) seen_start,
nvl(lead(seenat) over (partition by id order by seenat), seenat) seen_end
from t