【问题标题】:DB2 SQL Getting distinct value when grouping rowsDB2 SQL 在对行进行分组时获取不同的值
【发布时间】: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) 并引发另一个错误。有人可以解释一下编码的正确方法吗?谢谢!

【问题讨论】:

    标签: sql group-by db2 case distinct


    【解决方案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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-01-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-08-19
        • 1970-01-01
        相关资源
        最近更新 更多