DB2 SQL 在对行进行分组时获取不同的值
Posted
技术标签:
【中文标题】DB2 SQL 在对行进行分组时获取不同的值【英文标题】:DB2 SQL Getting distinct value when grouping rows 【发布时间】:2017-05-31 18:58:24 【问题描述】:BUSINESSTABLE 如下所示:
HOTEL_CHAIN HOTEL_LOCATION HOTEL_OWNER
_____________________________________________________
Marriott Las Vegas Nelson
Best Western New York Richards
Best Western San Francisco Smith
Marriott New York Nelson
Hilton Boston James
我正在尝试在 DB2 数据库中执行一条 SQL 语句,该语句按 HOTEL_CHAIN 对这些条目进行分组。如果组合在一起的行包含相同的 HOTEL_LOCATION 或 HOTEL_OWNER,则应保留该信息。否则,应显示“NULL”值。例如,两家万豪酒店都有相同的所有者 Nelson,因此我想在新表中显示该信息。但是,每家万豪酒店位于不同的位置,所以我想在该列中显示“NULL”。
结果表 (HOTELTABLE) 应如下所示:
HOTEL_CHAIN HOTEL_LOCATION HOTEL_OWNER
_____________________________________________________
Marriott NULL Nelson
Best Western NULL NULL
Hilton Boston James
我正在尝试使用以下 SQL 语句来完成此操作:
INSERT INTO HOTELTABLE(HOTEL_CHAIN,HOTEL_LOCATION,HOTEL_OWNER)
SELECT
HOTEL_CHAIN,
CASE COUNT(DISTINCT(HOTEL_LOCATION)) WHEN 1 THEN HOTEL_LOCATION ELSE 'NULL' END,
CASE COUNT(DISTINCT(HOTEL_OWNER)) WHEN 1 THEN HOTEL_OWNER ELSE 'NULL' END,
FROM BUSINESSTABLE GROUP BY HOTEL_CHAIN
我收到一个 SQL 错误 SQLCODE-119 A COLUMN OR EXPRESSION IN A HAVING CLAUSE IS NOT VALID。在我的案例陈述中,它似乎在抱怨第二个 HOTEL_LOCATION 和第二个 HOTEL_OWNER。我还尝试使用 DISTINCT(HOTEL_LOCATION) 并引发另一个错误。有人可以解释一下编码的正确方法吗?谢谢!
【问题讨论】:
【参考方案1】:不要使用COUNT(DISTINCT)
。使用MIN()
和MAX()
:
INSERT INTO HOTELTABLE(HOTEL_CHAIN,HOTEL_LOCATION,HOTEL_OWNER)
SELECT HOTEL_CHAIN,
(CASE WHEN MIN(HOTEL_LOCATION) = MAX(HOTEL_LOCATION)
THEN MIN(HOTEL_LOCATION) ELSE 'NULL'
END),
(CASE WHEN MIN(HOTEL_OWNER) = MAX(HOTEL_OWNER)
THEN MIN(HOTEL_OWNER) ELSE 'NULL'
END)
FROM BUSINESSTABLE
GROUP BY HOTEL_CHAIN;
注意事项:
为什么不COUNT(DISTINCT)
?它通常比MIN()
和MAX()
贵得多,因为它需要维护所有值的内部列表。
我不赞成使用名为'NULL'
的字符串值。似乎它旨在助长混乱。也许只是 NULL
价值本身?
【讨论】:
【参考方案2】:我同意 Gordon 的 null (gj Gordon)。
其他方法
INSERT INTO HOTELTABLE(HOTEL_CHAIN,HOTEL_LOCATION,HOTEL_OWNER)
select distinct f1.HOTEL_CHAIN,
case when f2.HasDiffLocation is not null then 'NULL' else f1.HOTEL_LOCATION end as HOTEL_LOCATION,
case when f3.HasDiffOwner is not null then 'NULL' else f1.HOTEL_OWNER end as HOTEL_OWNER
from BUSINESSTABLE f1
left outer join lateral
(
select 1 HasDiffLocation from BUSINESSTABLE f2b
where f1.HOTEL_CHAIN=f2b.HOTEL_CHAIN and f1.HOTEL_LOCATION<>f2b.HOTEL_LOCATION
fetch first rows only
) f2 on 1=1
left outer join lateral
(
select 1 HasDiffOwner from BUSINESSTABLE f3b
where f1.HOTEL_CHAIN=f3b.HOTEL_CHAIN and f1.HOTEL_OWNER<>f3b.HOTEL_OWNER
fetch first rows only
) f3 on 1=1
或者像这样:
INSERT INTO HOTELTABLE(HOTEL_CHAIN,HOTEL_LOCATION,HOTEL_OWNER)
select distinct f1.HOTEL_CHAIN,
ifnull(f2.result, f1.HOTEL_LOCATION) as HOTEL_LOCATION,
ifnull(f3.result, f1.HOTEL_OWNER) as HOTEL_LOCATION,
from BUSINESSTABLE f1
left outer join lateral
(
select 'NULL' result from BUSINESSTABLE f2b
where f1.HOTEL_CHAIN=f2b.HOTEL_CHAIN and f1.HOTEL_LOCATION<>f2b.HOTEL_LOCATION
fetch first rows only
) f2 on 1=1
left outer join lateral
(
select 'NULL' result from BUSINESSTABLE f3b
where f1.HOTEL_CHAIN=f3b.HOTEL_CHAIN and f1.HOTEL_OWNER<>f3b.HOTEL_OWNER
fetch first rows only
) f3 on 1=1
【讨论】:
以上是关于DB2 SQL 在对行进行分组时获取不同的值的主要内容,如果未能解决你的问题,请参考以下文章
BigQuery:如何在滚动时间戳窗口内对行进行分组和计数?
根据 SQL Server 2008 R2 中特定列中的模式更改对行进行分组