【问题标题】:SELECT columns outside applied WHERE filter选择应用的 WHERE 过滤器之外的列
【发布时间】:2018-01-26 10:32:20
【问题描述】:
+----------+---------+--------+------+------------+-----------+
| PersonID | OrderID | PlanID | Plan | Sdate      | Edate     |
+----------+---------+--------+------+------------+-----------+
| 1        | 1       | 312    | M    | 10/14/2016 | 1/30/2017 |
| 1        | 4       | 125    | A    | 10/18/2016 | 2/3/2017  |
| 1        | 7       | 411    | B    | 10/25/2016 | 4/7/2017  |
| 2        | 1       | 111    | E    | 10/31/2016 | 4/21/2017 |
| 2        | 3       | 312    | M    | 11/4/2016  | 4/28/2017 |
| 2        | 5       | 253    | L    | 11/29/2016 | 5/3/2017  |
| 3        | 1       | 50     | Q    | 12/2/2016  | 5/8/2017  |
| 3        | 2       | 12     | W    | 12/8/2016  | 6/8/2017  |
| 3        | 4       | 312    | M    | 12/22/2016 | 6/26/2017 |
| 3        | 6       | 53     | Z    | 12/27/2016 | 7/10/2017 |
+----------+---------+--------+------+------------+-----------+

我需要以下输出:

+----------+------------+-----------+----------+----------+
| PersonID | SDateM     | EDateM    | MinPlan1 | MinPlan2 |
+----------+------------+-----------+----------+----------+
| 1        | 10/14/2016 | 1/30/2017 | M        | A        |
| 2        | 11/4/2016  | 4/28/2017 | E        | M        |
| 3        | 12/22/2016 | 6/26/2017 | Q        | W        |
+----------+------------+-----------+----------+----------+

其中 SDateM 是当 Plan=M 时的 SDate,EDateM 是当 Plan=M 时的 Edate,MinPlan1 是一个人的最小 OrderID 的计划。 MinPlan2 是一个人的第二低 OrderID 的计划。

我在 WHERE 子句中应用了 PlanID=312,但这限制了我选择 MinPlans 的能力。我不知道如何编写提取MinPlan1和MinPlan2的代码。

尝试:

SELECT
    PersonID
    ,Sdate AS SDateM
    ,Edate AS EDateM
    ,MinPlan1
    ,MinPlan2
FROM 
    T1
WHERE 
    1 = 1
    AND PlanID = 312

【问题讨论】:

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


    【解决方案1】:

    您可以使用row_number 和条件聚合来做到这一点。

    SELECT PersonID
    ,MAX(CASE WHEN plan='M' then Sdate END) AS SDateM
    ,MAX(CASE WHEN plan='M' then Edate END) AS EDateM
    ,MAX(CASE WHEN rnum=1 then plan END) AS MinPlan1
    ,MAX(CASE WHEN rnum=2 then plan END) AS MinPlan2
    FROM (SELECT t1.*,row_number() over(partition by personId order by orderId) as rnum
          FROM T1
         ) t
    GROUP BY PersonID
    

    【讨论】:

      【解决方案2】:

      我认为条件聚合与row_number() 的组合可以解决问题:

      select personid, 
             min(case when plan = 'M' then sdate end) as sdateM,
             min(case when plan = 'M' then edate end) as edateM,
             max(case when seqnum = 1 then plan end) as plan_1,
             max(case when seqnum = 2 then plan end) as plan_2
      from (select t1.*,
                   row_number() over (partition by personid order by orderid) as seqnum
            from t1
           ) t1
      group by person_id;
      

      【讨论】:

        【解决方案3】:
        CREATE TABLE t_plan
        (personID INT,
         orderID INT,
         planID INT,
         plan_n VARCHAR(20),
         sdate DATE,
         edate DATE
        )
        
        INSERT INTO t_plan
        VALUES(1,1,312,'M','10/14/2016','1/30/2017'), 
        (1,4,125,'A','10/18/2016','2/3/2017'), 
        (1,7,411,'B','10/25/2016','4/7/2017'),  
        (2,1,111,'E','10/31/2016','4/21/2017'), 
        (2,3,312,'M','11/4/2016','4/28/2017'), 
        (2,5,253,'L','11/29/2016','5/3/2017'),  
        (3,1,50 ,'Q','12/2/2016','5/8/2017'),  
        (3,2,12 ,'W','12/8/2016','6/8/2017'),  
        (3,4,312,'M','12/22/2016','6/26/2017'), 
        (3,6,53 ,'Z','12/27/2016','7/10/2017')
        
        SELECT personid, 
               MIN(CASE WHEN plan_n = 'M' THEN sdate END) sdateM,
               MIN(CASE WHEN plan_n = 'M' THEN edate END) edateM,
               MAX(CASE WHEN rnum = 1 THEN plan_n END) minplan1,
               MAX(CASE WHEN rnum = 2 THEN plan_n END) minplan2
          FROM (SELECT *,
                       ROW_NUMBER() OVER (PARTITION BY personid ORDER BY orderid) rnum
                  FROM t_plan
               ) t
         GROUP BY personid;
        

        结果

        personid    sdateM      edateM      minplan1    minplan2
        1           2016-10-14  2017-01-30  M           A
        2           2016-11-04  2017-04-28  E           M
        3           2016-12-22  2017-06-26  Q           W
        

        【讨论】:

          猜你喜欢
          • 2014-09-09
          • 2016-12-16
          • 2016-07-15
          • 1970-01-01
          • 2017-11-07
          • 1970-01-01
          • 2021-06-25
          • 1970-01-01
          • 2019-08-22
          相关资源
          最近更新 更多