完全外部加入,合并和分组(哦,我的!)

时间:2018-06-10 17:07:09

标签: sql sql-server group-by coalesce full-outer-join

我将分两部分提出这个问题,因为我的逻辑可能很偏僻,如果是这样,语法并不重要。

  1. 我有10个查询。每个查询都会返回月份,供应商和计数(某个指标)。查询使用各种表,联接等。并非每个查询的输出中都存在所有月/供应商组合。我想将这些组合成一个可以在Excel中导出和旋转的数据集。
  2. 我希望输出看起来像这样:

    Month | Supplier | Metric1 |Metric2 |..| Metric 10
    2018-01 | Supp1 | _value_ | _value_ |...| _value_ |
    2018-01 | Supp2 | NULL | _value_ |...| NULL
    

    实现这一目标的最佳/最简单/最有效的方法是什么?

    1. 我已尝试过各种方法来完成上述工作,但我似乎无法正确理解语法。我想做一个非常简单的测试用例并在它上构建,但我只对db有选择权限,所以我无法测试它。我能够创建一个查询,至少不会导致任何波浪形的红色错误行,但对更大的问题应用相同的逻辑并不起作用。
    2. 这就是我所拥有的:

       create table test1(name varchar(20),credit int);
       insert into test1 (name, credit) values ('Ed',1),('Ann',1),('Jim',1),('Ed',1),('Ann',1);
       create table test2 (name varchar(10), debit int);
       insert into test2 (name, debit) values ('Ann',1),('Sue',1),('Sue',1),('Sue',1);
      
       select
          coalesce(a.name, b.name) as name,
          cred,
          deb
       from
          (select name, count(credit) as cred
              from test1 
              group by name) a
          full outer join 
          (select name, count(debit) as deb
              from test2
              group by name) b  on 
           a.name =b.name;
      

      我走向正确的道路吗?

      更新:根据Gordon的输入,我在前两个查询中尝试了这个:

      select Month, Supp,
          sum(case when which = 1 then metric end) as Exceptions,
          sum(case when which = 2 then metric end) as BackOrders
      from (
              (
               select Month, Supp, metric, 1 as which
               from (
                      select (convert(char(4),E.PostDateTime,120)+'-'+convert(char(2),E.PostDateTime,101)) as Month, E.TradingPartner as Supp, count(distinct(E.excNum)) as metric
                      from db..TrexcMangr E
                      where (E.DSHERep in ('AVR','BTB') OR E.ReleasedBy in ('AVR','BTB')) AND year(E.PostDateTime) >= '2018'
                    ) a
               )
      
               union all
      
              (
               select Month, Supp, metric, 2 as which
               from (
                      select (convert(char(4),T.UpdatedDateTime,120)+'-'+convert(char(2),T.UpdatedDateTime,101)) as Month, P.Supplier as Supp, count(*) as metric
                      from db1..trordertext T
                          inner join mdid_Tran..trOrderPO P on P.PONum = T.RefNum
                      where T.TextType = 'BO' AND (T.CreatedBy in ('AVR','BTB') OR T.UpdatedBy in ('AVR','BTB')) AND year(UpdatedDateTime) >=2018
                    ) b
              )
           ) q
      group by Month, Supp
      

      ...但我错误地收到了一个小组。

2 个答案:

答案 0 :(得分:0)

一种方法使用union allgroup by

select month, supplier,
       sum(case when which = 1 then metric end) as metric_01,
       sum(case when which = 2 then metric end) as metric_02,
       . . .
from ((select Month, Supplier, Metric, 1 as which
       from (<query1>) q
       . . .
      ) union all
      (select Month, Supplier, Metric, 2 as which
       from (<query2>) q
       . . .
      ) union all
      . . .
     ) q
group by month, supplier;

答案 1 :(得分:0)

SELECT
    CalendarMonthStart,
    Supp,
    SUM(CASE WHEN metric_id = 1 THEN metric END) as Exceptions,
    SUM(CASE WHEN metric_id = 2 THEN metric END) as BackOrders
FROM
(
    SELECT
        DATEADD(month, DATEDIFF(month, 0, E.PostDateTime), 0)   AS CalendarMonthStart,
        E.TradingPartner            AS Supp,
        COUNT(DISTINCT(E.excNum))   AS metric,
        1                           AS metric_id
    FROM
        db..TrexcMangr E
    WHERE
        (      E.DSHERep    in ('AVR','BTB')
            OR E.ReleasedBy in ('AVR','BTB')
        )
        AND E.PostDateTime >= '2018-01-01'
    GROUP BY
        1, 2

    UNION ALL

    SELECT
        DATEADD(month, DATEDIFF(month, 0, T.UpdatedDateTime), 0)   AS CalendarMonthStart,
        T.UpdatedDateTime,
        P.Supplier                  AS Supp,
        COUNT(*)                    AS metric,
        2                           AS metric_id
    FROM
        db1..trordertext T
    INNER JOIN
        mdid_Tran..trOrderPO P
            ON  P.PONum = T.RefNum
    WHERE
        (      T.CreatedBy in ('AVR','BTB')
            OR T.UpdatedBy in ('AVR','BTB')
        )
        AND T.TextType = 'BO'
        AND T.UpdatedDateTime >= '2018-01-01'
    GROUP BY
        1, 2
)
   combined
GROUP BY
    CalendarMonthStart,
    Supp