【问题标题】:SQL issue with Case statement and joining multiple tablesCase语句的SQL问题和连接多个表
【发布时间】:2017-08-07 15:21:09
【问题描述】:

这是两个表的示例(请参阅 SQLFiddle),我尝试创建一个 select 语句,其中一个表是查找表(Facility),另一个是数据表(WOENTITY),我想从中选择获取 facititynames查找并且每当它找到多个设施ID条目时,只需将文本写入“多个位置”,或者如果它找到空或零然后写入“未知”,否则只需写入设施名称,我试图做一个案例以用单个条目替换多个计数。任何帮助表示赞赏。

链接到 SQL Fiddle:Click Here

这是表格外观的屏幕截图,Table WOEntity 和 Table Facility Image showing the table schema and expected end result

我首先想到从 WOEntity 表中获取多个位置 ID 的计数,然后创建一个 select Case 语句但没有用,这里是草稿代码。

select e.WOID, count(e.ENTITYUID) as CNT, 
    (case   
            when e.ENTITYUID <> '0' and count(e.ENTITYUID) <=1 then
                (Select FACILITYNAME from FACILITY l where e.ENTITYUID = 
                  l.FACILITYID)
            when count(e.ENTITYUID) > 2 then 'MULTIPLE FACILITIES'
            else 'UNKNOWN LOCATIONS'
    end) as facilityName
 From WOENTITY e
group by e.WOID order by WOID;

【问题讨论】:

  • 您的预期结果是什么?
  • 感谢您的回复,预期的结果是我只想按 WOID 而不是实体进行分组。我想查看两列,不同的 WOID(WOID 的每个条目)和设施名称(来自查找)
  • OP,在为您的问题提供其他信息时,请编辑您的原始问题。谢谢,欢迎来到 Stack Overflow。
  • @STLDeveloper,感谢您的建议,会做的!

标签: sql sql-server select sql-server-2012


【解决方案1】:

我个人会使用 JOIN 而不是相关子查询来执行此操作,然后在 case 表达式中使用 COUNT

SELECT  e.WOID,
        CASE WHEN COUNT(f.FACILITYID) = 0 THEN 'UNKNOWN LOCATIONS'
            WHEN COUNT(f.FACILITYID) > 1 THEN 'MULTIPLE FACILITIES'
            ELSE MAX(f.FACILITYNAME)
        END AS facilityName
FROM    WOENTITY AS e
        LEFT JOIN FACILITY AS f
            ON f.FACILITYID = e.ENTITYUID
GROUP BY e.WOID
ORDER BY e.WOID;

SQL Fiddle

由于您处理 JOIN 匹配的多条记录或零条记录的情况,当您到达 ELSE 时,您只有一条记录,因此尽管您使用的是 MAX 聚合函数,您只有一个输入行,所以除了允许您选择设施名称而不按其分组之外,这并没有真正做任何事情。

编辑

我刚刚注意到加拿大应该显示为多个位置,即使它们中只有一个存在于设施表中,在这种情况下,您需要稍微更改大小写表达式,将 COUNT(f.FACILITYID) 更改为 COUNT(*) 第二个谓词:

SELECT  e.WOID,
        CASE WHEN COUNT(f.FACILITYID) = 0 THEN 'UNKNOWN LOCATIONS'
            WHEN COUNT(*) > 1 THEN 'MULTIPLE FACILITIES'
            ELSE MAX(f.FACILITYNAME)
        END AS facilityName
FROM    WOENTITY AS e
        LEFT JOIN FACILITY AS f
            ON f.FACILITYID = e.ENTITYUID
GROUP BY e.WOID
ORDER BY e.WOID;

SQL Fiddle

【讨论】:

  • 感谢您的回复,编辑看起来不错,我正在用实际数据(数千条记录)测试结果,到目前为止一切都很好。我还发现@Horaciux 的解决方案也很好用。假设您和 Horaciux 都做同样的事情是否安全?将在更多测试中发布结果
【解决方案2】:

正如声明对您所说,您错过了 params 的一个 gorup ... 类似:

select e.WOID, count(e.ENTITYUID) as CNT, 
    (case   
            when e.ENTITYUID <> '0' and count(e.ENTITYUID) <=1 then
                (Select FACILITYNAME from FACILITY l where e.ENTITYUID = 
                  l.FACILITYID) 
            when count(e.ENTITYUID) > 2 then 'MULTIPLE FACILITIES'
            else 'UNKNOWN LOCATIONS'
    end) as facilityName
 From WOENTITY e
group by e.WOID,e.ENTITYUID order by WOID;

【讨论】:

  • 感谢您的回复,我不想按 EntityUid 分组,因为这会使不同的 WOID 消失,我希望看到每个 WOID 及其设施名称的单个条目。从您上面的代码中,我看到 WOID 重复了多次
【解决方案3】:

请试试这个

Select FACILITYID,
    CASE WHEN (SELECT COUNT(*) 
               FROM  WOEnTITY 
               WHERE WOEnTITY.ENTITYUID = FACILITYID)  > 0 
         THEN 'MULTIPLE LOCATIONS' 
         ELSE '' 
    END
FROM FACILITY

【讨论】:

    【解决方案4】:

    您可以如下查询:

    Select Row_Number() over(order by Id) as Id, Woid, Case when FACILITYID is null then 'UNKNOWN LOCATIONS'
                   when RowCnt > 1 then 'MULTIPLE OFFICES' else FACILITYNAME end as FacilityName,
                   RowCnt as CountFacilities 
                   from (
        Select *, RowCnt = count(EntityUid) over(partition by woid),
        RowN = Row_Number() over(Partition by woid order by Id)
        from WOENTITY we
        left join Facility f
        on we.ENTITYUID = f.FACILITYID
    ) a
    Where a.RowN = 1
    

    输出如下:

    
    +----+---------+-------------------+-----------------+
    | Id |  Woid   |   FacilityName    | CountFacilities |
    +----+---------+-------------------+-----------------+
    |  1 | Canada  | MULTIPLE OFFICES  |               2 |
    |  2 | Germany | GREEN             |               1 |
    |  3 | India   | GREEN             |               1 |
    |  4 | UK      | RED               |               1 |
    |  5 | US      | MULTIPLE OFFICES  |               3 |
    |  6 | JAPAN   | UNKNOWN LOCATIONS |               1 |
    +----+---------+-------------------+-----------------+
    

    【讨论】:

      【解决方案5】:

      这是对@GarethD 答案的修改,考虑了类似于“加拿大”的情况

        SELECT  e.WOID,
              CASE WHEN COUNT(f.FACILITYID) = 0 THEN 'UNKNOWN LOCATIONS'
                  WHEN COUNT(f.FACILITYID) >0 and  COUNT(coalesce(f.FACILITYID,'x'))>COUNT(f.FACILITYID)  then 'MULTIPLE OFFICES'
                  WHEN COUNT(f.FACILITYID) > 1 then 'MULTIPLE OFFICES'
                  ELSE MAX(f.FACILITYNAME)
              END AS facilityName
      FROM    WOENTITY AS e
              LEFT JOIN FACILITY AS f
                  ON f.FACILITYID = e.ENTITYUID
      GROUP BY e.WOID
      ORDER BY e.WOID;
      

      【讨论】:

      • @Horacius,感谢您的回复,我不想按 EntityUid 分组,因为这会使不同的 WOID 消失,我希望看到每个 WOID 及其设施名称的单个条目。从您上面的代码中,我看到 WOID 重复了多次
      • @Abdul 看看我的编辑,它现在给你带来了预期的结果。
      猜你喜欢
      • 2016-07-31
      • 1970-01-01
      • 1970-01-01
      • 2015-10-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多