2

使用 SQL,您如何使用两条记录来查找位置、保留该位置并使用该记录将“Nonsense”值替换为保留的位置?我将展示到目前为止我能够写的内容,然后写下我仍在尝试弄清楚的内容:

SELECT * FROM "TABLES". "ACCTS_OF_SUPERHEROS".;

DECLARE @count_rows INT = 0;
DECLARE @row_total INT = 0;
DECLARE @refAcctNum INT = 0;
DECLARE @selectedPlaceName TINYTEXT;

SET @row_total = SELECT COUNT (*)

WHILE countRows < row_total
    for each acct_num store value in refAcctNum. 
    Using refAcctNum find place: "Gotham City", "Central City", "Metropolis", "Smallville", "Star City", "Fawcett City" store that in selectedPlaceName.
    If refAccountNumber has Nonsense then replace with selectedPlaceName record
    otherwise add + 1 to countRows and repeat. 
END

当前表格数据;“ACCTS_OF_SUPERHEROS”表

| row | acct_num | exact_address    | place
| --- | -------- |------------------|--------
| 1   | 049403   | 344 Clinton Str  | Metropolis 
| 2   | 049403   | 344 Clinton Str  | Nonsense
| 3   | 049206   | 1007 Mountain Dr | Gotham City
| 4   | 049206   | 1007 Mountain Dr | Gotham City
| 5   | 049206   | 1096 Show Dr.    | Fawcett City
| 6   | 049206   | 1096 Show Dr.    | Nonsense
| 7   | 049206   | NULL             | Nonsense
| 8   | 049291   | 1938 Sullivan Pl | Smallville
| 9   | 049293   | 700 Hamilton Str | Central City
| 10  | 049396   | 800 Nonsense Way | Nonsense
| 11  | 049396   | NULL             | Nonsense

期望的输出

| row | acct_num | exact_address    | place
| --- | -------- |------------------|--------
| 1   | 049403   | 344 Clinton Str  | Metropolis 
| 2   | 049403   | 344 Clinton Str  | Metropolis
| 3   | 049206   | 1007 Mountain Dr | Gotham City
| 4   | 049206   | 1007 Mountain Dr | Gotham City
| 5   | 049206   | 1096 Show Dr.    | Fawcett City
| 6   | 049206   | 1096 Show Dr.    | Fawcett City
| 7   | 049206   | NULL             | Fawcett City
| 8   | 049291   | 1938 Sullivan Pl | Smallville
| 9   | 049293   | 700 Hamilton Str | Central City
| 10  | 049396   | 800 Tidal Way    | Star City
| 11  | 049396   | NULL             | Star City
4

2 回答 2

1

您可以使用窗口函数:

select t.*,
       max(case when place <> 'Nonsense' then place end) over (partition by acct_num) as imputed_place
from t;

NULL如果所有行都是'Nonsense'给定的,则返回acct_num。您可以使用COALESCE()其他内容替换该值。

于 2021-09-10T15:48:03.770 回答
0

我正在阅读 Snowflake 中可用的窗口函数列表,并认为您将需要一个新的窗口函数。也许有人可以找到更内置的方法,但无论如何,这里有一个用户定义的表函数 REPLACE_WITH_LKG 实现为窗口函数,它将用最后一个已知的好值替换坏值。只要我打算写它,我就认为它可能是通用的,所以它使用正则表达式和 JavaScript RegExp 选项匹配“坏”值。

create or replace function REPLACE_WITH_LKG("VALUE" string, "REGEXP" string, "REGEXP_OPTIONS" string)
returns table(LKG_VALUE string)
language javascript
strict immutable
as
$$
{
    initialize: function (argumentInfo, context) {
        this.lkg = "";
    },
    processRow: function (row, rowWriter, context) {
        const rx = new RegExp(row.REGEXP, row.REGEXP_OPTIONS);
        if (!rx.test(row.VALUE)) {
            this.lkg = row.VALUE;
        }
        rowWriter.writeRow({LKG_VALUE: this.lkg});
    },
    finalize: function (rowWriter, context) {},
}
$$;

select S.*, LKG.LKG_VALUE as PLACE
from superhero S, table(REPLACE_WITH_LKG(PLACE, 'Nonsense', 'ig')
over(partition by null order by "ROW")) LKG;
;

性能说明;数据显示的方式除了整个表之外没有分区。那是因为按帐户进行分区的一个明显位置将不起作用。如果使用帐户,第 10 行将从不同的窗口中获取其值,因此示例数据的显示方式需要是一个跨越整个表的窗口。这不会很好地并行化,对于非常大的表应该避免。

于 2021-09-11T04:48:48.267 回答