SQL:根据另一个表中多个行的值选择一个值

时间:2013-07-11 17:11:46

标签: sql

我有一个表NETWORKS,每个网络可以有多个CIRCUITS。每个网络都具有全部状态(红色/黄色/绿色),每个电路都具有单独状态(红色/绿色)。电路的状态均为手动设置。网络的状态如下:

  • 如果所有电路都是绿色 - >绿色
  • 如果所有电路都是红色的 - >红色
  • 如果至少有1个电路,但并非所有电路都是绿色 - >黄
  • 如果没有电路 - > NULL(无状态)

我正在尝试选择所有网络,其状态由SELECT动态确定,而不是必须将状态保存和管理为表中的列。我无法找到一种有效的方法来做到这一点。我现在的工作原理(两个都是小表,< 100,具有相对静态数据量的行),但效率极低,我希望有更好的方法。

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

3 个答案:

答案 0 :(得分:3)

这是一种方式:

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

答案 1 :(得分:1)

我认为这应该做你想要的。它也应该比使用一堆子查询更快。

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

答案 2 :(得分:1)

我的第一个想法是:

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)