首页 > 解决方案 > 您能否成功地将多个条件嵌套在 partition by 语句中?

问题描述

我在 Fiddle 中构建了这个示例表:https ://www.db-fiddle.com/f/pu1PkjzKCM9VRciznkJc4L/7

我正在为帐号和序列号重新标记地区。您可以看到我尝试更改数据并添加具有正确区域的新列的表架构和查询。问题是我的结果,你会在最后看到。我想找到一种方法首先通过serial_number,我确定serial_numbers 是跟踪区域的最佳方法,然后在serial_numbers 为空时添加正确的区域名称时的acct_num。

但是,虽然我的程序主要用于此目的。当有一个 acct_num 并且没有 serial_number 时,它不会只是抛出它找到的最后一个“正确”区域。我需要这个程序来做到这一点。我在想也许是一个嵌套的case语句?我曾尝试在先前存在的 CASE 和 PARTITION BY 语句中执行此操作,但我一直没有成功,它一直抛出语法错误。

我在想...(PARTITION BY WHEN serial_number='NULL' THEN acct_num ELSE serial_number),但这总是会引发错误。

任何帮助表示赞赏!

SQL 架构

'''

CREATE TABLE t (
"row" INTEGER,
"acct_num" TEXT,
"serial_number" TEXT,
"site_address" TEXT,
"city" TEXT,
"territory_name" TEXT
);

INSERT INTO t
("row", "acct_num", "serial_number", "site_address", "city", "territory_name")
VALUES
('1', '049403', 'TH-530', '344 Clinton Str', 'Metropolis', 'Central'),
('2', '049403', 'TH-530', '344 Clinton Str', 'Metropolis', 'Central'),
('3', '049206', 'GO-650', '1007 Mountain Dr', 'Gotham City', 'Gotham City'),
('4', '049206', 'GO-650', '1007 Mountain Dr', 'Gotham City', 'Gotham City'),
('5', '049206', 'GO-650', 'NULL', 'NULL', 'N/A'),
('6', '049206', 'TJO-560', 'NULL', 'NULL', 'NULL'),
('7', '049291', 'SM-708', '1938 Sullivan Pl', 'Smallville', 'No Territory'),
('8', '049293', 'TH-533', '700 Hamilton Str', 'Central City', 'Central'),
('9', '049396', 'AL-670', '800 Ellsmore Way', 'Alberty Township', 'South'),
('10', '049396', 'KILO-680', '600 Nukem Drive', 'Duke City', 'Southeast'),
('11', '049396', 'JALO-605', '5806 London Way', 'Hampshire', 'Northeast'),
('12', '049396', 'NULL', 'NULL', 'NULL', 'No Territory');

'''

SQL查询

'''

 select row, 
   acct_num, 
   serial_number,
   site_address,
 MAX(
 CASE
 WHEN territory_name <> 'N/A' AND territory_name <> 'No Territory' 
 THEN territory_name
 WHEN serial_number = 'NULL' 
 THEN territory_name
 END) 
 over (PARTITION BY serial_number) as imputed_place
 from t
 order by row

'''

SQL查询结果

| row | acct_num | serial_number  | site_address    | imputed_place
| ----|----------|----------------|-----------------|---------------
| 1   | 049403   | TH-530         | 344 Clinton Str | Central
| 2   | 049403   | TH-530         | 344 Clinton Str | Central
| 3   | 049206   | GO-650         | 1007 Mountain Dr| Gotham City
| 4   | 049206   | GO-650         | 1007 Mountain Dr| Gotham City
|  5  | 049206   | GO-650         |  NULL           | Gotham City
|  6  | 049206   |  TJO-560       | NULL            |   NULL
|  7  | 049291   |  SM-708        | 1938 Sullivan Pl|   null
|  8  | 049293   |  TH-533        | 700 Hamilton Str| Central
|  9  | 049396   |  AL-670        | 800 Ellsmore Way|   South
| 10  | 049396   |  KILO-680      | 600 Nukem Drive |   Southeast
| 11  | 049396   |  JALO-605      | 5806 London Way |   Northeast
| 12  | 049396   |  NULL          | NULL            |   No Territory <- should be Northeast!!!

'''

DB Fiddle – 由英国 Status200 用 ♥ 制作。使用条款 • 隐私/Cookie 政策 • Status200 Ltd © 2018

标签: sqlsnowflake-cloud-data-platformdomo

解决方案


我试图重新创建您的结果(包括第 12 行),列行是解决方案/数据的一部分吗?

我采用的方法是按序列号创建有效值的映射表,因此键+值必须是唯一的,否则我们将结果从 12 行分解为...更多!当我查看不是这种情况的帐号时,这对序列号很有效。没有唯一的映射,确定第 12 行应该是“东北”的规则是什么?

如果它基于行,那么结果很容易,我将在下面提供解决方案,

with map_by_serial_no as (
select distinct "serial_number"
  , "territory_name"
  from t
  where "serial_number" <> 'NULL'
    and "territory_name" <> 'N/A'
  and "territory_name" <> 'NULL'
) 
select t."row"
, t."acct_num"
, t."serial_number"
, t."site_address"
, t."city"
, t."territory_name"
, case when t."serial_number" = 'NULL' then lag(t."territory_name") over (order by "row")
   when t."territory_name" in ('NULL', 'No Territory', 'N/A') then u."territory_name"
   else t."territory_name" end as imputed_territory
from t
left join map_by_serial_no u
on t."serial_number" = u."serial_number"
order by "row";

但是请注意,NULL 应该是没有值,而在此示例中它是带引号的字符串。


推荐阅读