【问题标题】:SQL: selecting a value based on values from a number of rows in another tableSQL:根据另一个表中多行的值选择一个值
【发布时间】:2013-07-11 17:11:46
【问题描述】:

我有一个表 NETWORKS,其中每个网络可以有多个 CIRCUITS。每个网络都有一个整体状态(红色/黄色/绿色),每个电路都有一个单独的状态(红色/绿色)。每个电路的状态都是手动设置的。网络状态如下:

  • 如果它的所有电路都是绿色的 --> 绿色
  • 如果它的所有电路都是红色的 --> 红色
  • 如果至少 1 个(但不是全部)电路为绿色 --> 黄色
  • 如果没有电路 --> NULL(无状态)

我正在尝试选择所有网络,它们的状态由 SELECT 动态确定,而不必将状态作为表中的一列保存和管理。我想不出一种有效的方法来做到这一点。我现在的工作(都是小表,

SELECT
(CASE 
    WHEN (
        SELECT COUNT(*) 
        FROM NETWORK_CIRCUITS 
        WHERE network_id = N.network_id
    ) = 0 THEN 'noStatus'
    WHEN (
        SELECT COUNT(*) 
        FROM NETWORK_CIRCUITS 
        WHERE network_id = N.network_id
        AND [status] = 'greenStatus'
    ) = (
        SELECT COUNT(*) 
        FROM NETWORK_CIRCUITS 
        WHERE network_id = SSN.network_id
    ) THEN 'greenStatus'
    WHEN (
        SELECT COUNT(*) 
        FROM NETWORK_CIRCUITS 
        WHERE network_id = N.network_id
        AND [status] = 'redStatus'
    ) = (
        SELECT COUNT(*) 
        FROM NETWORK_CIRCUITS 
        WHERE network_id = N.network_id
    ) THEN 'redStatus'
    ELSE 'yellowStatus'
END) network_status
FROM NETWORKS N

【问题讨论】:

    标签: sql


    【解决方案1】:

    这是一种方法:

    SELECT
        CASE 
            WHEN CircuitCount IS NULL      THEN 'noStatus'
            WHEN GreenCount = CircuitCount THEN 'greenStatus'
            WHEN GreenCount = 0            THEN 'redStatus'
            ELSE 'yellowStatus'
        END As network_status
    FROM NETWORKS As N
    LEFT JOIN
    (   SELECT  COUNT(*) As CircuitCount,
                COUNT(NULLIF([status],'redStatus')) As GreenCount,
                network_id
        FROM    NETWORK_CIRCUITS
        GROUP BY network_id
    )   As C    ON N.network_id = C.network_id
    

    【讨论】:

      【解决方案2】:

      我的第一个想法是:

      select network_id, case when green=0 and red=0 then null when green=0 then 'red' else when red=0 then 'green' else 'yellow' end as status
      from
      (select n.network_id,
        sum(case when c.status='green' then 1 else 0 end) as green,
        sum(case when c.status='red' then 1 else 0 end) as red
      from network n
      join circuit c on c.network_id=n.network_id
      group by n.network_id)
      

      【讨论】:

      • 糟糕,应该是“左连接电路”,否则我们永远不会得到空状态的情况。
      【解决方案3】:

      我认为这应该可以满足您的需求。它也应该比使用一堆子查询更快。

      SELECT CASE
               WHEN circuits.network_id is NULL THEN 'No Status'
               WHEN circuits.greenCount = circuits.totalCircuits THEN 'Green'
               WHEN circuits.greenCount >= 1 and circuits.redCount >= 1 THEN 'Yellow'
               WHEN circuits.redCount = circuits.totalCircuits THEN 'Red'
             END as network_status
            , N.network_id
      FROM NETWORKS N
      LEFT JOIN 
          (SELECT network_id
                 , sum(CASE WHEN [status] = 'redStatus' THEN 1 ELSE 0 END) as redCount
                 , sum(CASE WHEN [status] = 'greenStatus' THEN 1 ELSE 0 END) as greenCount
                 , count(*) as totalCircuits
          FROM NETWORK_CIRCUITS
          GROUP BY network_id) as circuits ON circuits.network_id = N.network_id
      

      【讨论】:

      • 我不小心投了反对票,对不起(鼠标片状)。如果您对其进行一些小的修改,我可以更改我的投票...
      • @RBarryYoung 稍微编辑了我的答案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-07-22
      • 2012-01-30
      • 2020-02-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多