选择为状态如果子图表行包含值

时间:2017-03-20 13:06:06

标签: sql sql-server sql-server-2008-r2

我有2个名为Order和OrderDetails的表

订单表

    orderID   orderDate     OrderUserId
1    10       01.01.2010      .....
2    20       05.05.2011      .....

OrderDetails表

 DetailID   OrderIdOfDetail  DetailProductID   DetailStatusID
1    25            10               xxx                1
2    26            10               xxx                2
3    27            10               xxx                2
4    28            10               xxx                0
5    29            10               xxx                1
6    30            20               xxx                1
7    31            20               xxx                2
8    32            20               xxx                0

DetailStatusId用于关闭,待定,取消bla ...

例如,我想选择orderID:10。 如果明细行包括DetailsS​​tatusID 1,则选择订单状态为"待定"。 如果明细行包括DetailsS​​tatusID 2,则选择订单状态为"打开"。 如果所有DetailsS​​tatusID都相等且0选择订单状态为"已关闭"

我试过"如果存在"但无法取得成功。 我该怎么办?

3 个答案:

答案 0 :(得分:3)

您可以使用如下查询:

SELECT o.orderID, 
       CASE 
          WHEN MAX(CASE WHEN DetailStatusID = 1 THEN 1 ELSE 0 END) +
               MAX(CASE WHEN DetailStatusID = 2 THEN 1 ELSE 0 END) +
               MAX(CASE WHEN DetailStatusID = 0 THEN 1 ELSE 0 END) >= 2
             THEN 'MultiStatus'
          WHEN COUNT(CASE WHEN DetailStatusID = 1 THEN 1 END) > 0 THEN 'Pending'
          WHEN COUNT(CASE WHEN DetailStatusID = 2 THEN 1 END) > 0 THEN 'Open'
          WHEN MAX(DetailStatusID) = 0 THEN 'Closed'
       END AS Status
FROM  Order AS o
JOIN OrderDetails AS od ON o.orderID = od.OrderIdOfDetail  
GROUP BY orderID 

查询使用CASE表达式来计算Status字段:

  • 首先检查订单是否包含带有DetailStatusID = 1至少一个记录。如果它确实“等待”'归还。
  • 然后检查订单是否包含带有DetailStatusID = 2至少一个记录。如果它确实打开了'归还。
  • 然后检查该组的所有记录是否都有DetailStatusID = 0。在这种情况下,'已关闭'退回。我假设DetailStatusID不能采取否定的vaues。

答案 1 :(得分:2)

这使用left join到派生表(子查询),该表使用条件聚合来计算不同的DetailStatusId。如果由于某种原因Other没有相应的详细记录,这也会为Status返回OrderId的结果。

select o.*
  , [Status]=case 
      when od.Status0 > 0 and od.Status0 = od.DetailCount 
        then 'Closed'
      when od.Status1 > 0
        then 'Pending'
      when od.Status2 > 0
        then 'Open'
      else 'Other'
      end
from orders as o
  left join (
    select 
        OrderIdOfDetail
      , DetailCount = count(*)
      , Status0 = sum(case when DetailStatusId = 0 then 1 else 0 end)
      , Status1 = sum(case when DetailStatusId = 1 then 1 else 0 end)
      , Status2 = sum(case when DetailStatusId = 2 then 1 else 0 end)
    from OrderDetails 
    group by OrderIdOfDetail
  ) as od 
    on o.OrderId = od.OrderIdOfDetail

rextester演示:http://rextester.com/YPA79670

查询结果:

+---------+---------------------+-------------+---------+
| orderID |      orderDate      | OrderUserId | Status  |
+---------+---------------------+-------------+---------+
|      10 | 01.01.2010 00:00:00 |           1 | Pending |
|      20 | 05.05.2011 00:00:00 |           2 | Pending |
+---------+---------------------+-------------+---------+

子查询只有结果:

+-----------------+-------------+---------+---------+---------+
| OrderIdOfDetail | DetailCount | Status0 | Status1 | Status2 |
+-----------------+-------------+---------+---------+---------+
|              10 |           5 |       1 |       2 |       2 |
|              20 |           3 |       1 |       1 |       1 |
+-----------------+-------------+---------+---------+---------+

答案 2 :(得分:0)

select *, case when DetailStatusID = '1' then 'Pending'
               when DetailStatusID = '2' then 'Open'
               when DetailStatusID = '0' then 'Closed'
          end as OrderStatusDescription
From OrderDetails
Where OrderIdOfDetail = '10'