在输出中显示空记录

时间:2018-02-23 18:40:15

标签: sql-server-2012

我通过不同查询的UNION查询不同项类型的数据(多列)。如果特定项类型的任何列中没有值,则该记录不会显示。但是,我需要与每个项目类型相关的所有行(包括空行)。空行可以显示0。

我的数据是:

create table sales_table ([yr] int, [qtr] varchar(40), [item_type] varchar(40), [sale_price] int);
create table profit_table ([yr] int, [qtr] varchar(40), [item_type] varchar(40), [profit] int);
create table item_table ([item_type] varchar(40));

insert into sales_table values
(2010,'Q1','abc',31),(2010,'Q1','def',23),(2010,'Q1','mno',12),(2010,'Q1','xyz',7),(2010,'Q2','abc',54),(2010,'Q2','def',67),(2010,'Q2','mno',92),(2010,'Q2','xyz',8);

insert into profit_table values
(2010,'Q1','abc',10),(2010,'Q1','def',6),(2010,'Q1','mno',23),(2010,'Q1','xyz',7),(2010,'Q2','abc',21),(2010,'Q2','def',13),(2010,'Q2','mno',15),(2010,'Q2','xyz',2);

insert into item_table values
('abc'),('def'),('ghi'),('jkl'),('mno'),('xyz');

我的查询是:

SELECT a.yr, a.qtr, b.item_type, MAX(a.sales), MAX(a.avg_price), MAX(a.profit)
FROM 
    (SELECT [yr], [qtr], 
       CASE
       WHEN item_type = 'abc' THEN 'ABC'
       WHEN item_type = 'def' THEN 'DEF'
       WHEN item_type = 'ghi' THEN 'GHI'
       WHEN item_type = 'jkl' THEN 'JKL'
       WHEN item_type IN ('mno', 'xyz') THEN 'Other'
       END AS [item_type], 
       COUNT(sale_price) OVER (PARTITION BY yr, qtr, item_type) [sales], 
       AVG(sale_price) OVER (PARTITION BY yr, qtr, item_type) [avg_price],
       NULL [profit] 
     FROM sales_table
     WHERE yr >=2010
     UNION ALL
     SELECT yr, qtr, 
       CASE
       WHEN item_type = 'abc' THEN 'ABC'
       WHEN item_type = 'def' THEN 'DEF'
       WHEN item_type = 'ghi' THEN 'GHI'
       WHEN item_type = 'jkl' THEN 'JKL'
       WHEN item_type IN ('mno', 'xyz') THEN 'Other'
       END AS [item_type], 
       NULL [sales], 
       NULL [avg_price],
       SUM(profit) OVER (PARTITION BY yr, qtr, item_type) [profit] 
     FROM profit_table
     WHERE yr >=2010
    ) a
FULL OUTER JOIN
   (SELECT      
      CASE
      WHEN item_type = 'abc' THEN 'ABC'
      WHEN item_type = 'def' THEN 'DEF'
      WHEN item_type = 'ghi' THEN 'GHI'
      WHEN item_type = 'jkl' THEN 'JKL'
      WHEN item_type IN ('mno', 'xyz') THEN 'Other'
      END AS [item_type] 
    FROM item_table
    WHERE item_type in ('abc','def','ghi','jkl','mno','xyz')
   ) b
ON a.item_type = b.item_type
GROUP BY a.yr, a.qtr, b.item_type
ORDER BY a.yr, a.qtr, b.item_type;

目前的输出是这样的:

yr      qtr     item_type  sales    avg_price   profit  
(null)  (null)  GHI        (null)   (null)      (null)
(null)  (null)  JKL        (null)   (null)      (null)
2010    Q1      ABC         1       31          10
2010    Q1      DEF         1       23          6
2010    Q1      Other       1       12          23
2010    Q2      ABC         1       54          21
2010    Q2      DEF         1       67          13
2010    Q2      Other       1       92          15

我想要的是如下所示。

yr      qtr item_type   sales   avg_price   profit  
2010    Q1  ABC         1       31          10
2010    Q1  DEF         1       23          6
2010    Q1  GHI         0       0           0
2010    Q1  JKL         0       0           0
2010    Q1  Other       2       9.5         30
2010    Q2  ABC         1       54          21
2010    Q2  DEF         1       67          13
2010    Q2  GHI         0       0           0
2010    Q2  JKL         0       0           0
2010    Q2  Other       2       50          17

请告知。

2 个答案:

答案 0 :(得分:0)

以下是使用union all + group by

的其他选项
select
    max(max([year])) over ()
    , max(max([quarter])) over ()
    , [item_type]
    , isnull(max([sales]), 0)
    , isnull(max([avg price]), 0)
    , isnull(max([profit]), 0)
from (
    SELECT [year], [quarter], [item_type], [sales], [avg price], [profit] 
    FROM sales_table
    union all
    select distinct null, null, item_type, null, null, null
    from item_table
) t
group by [item_type]

使用full join的查询应该有效,但您必须处理null值。我认为应该是这样的:

SELECT 
    max(a.year) over ()
    , max(a.quarter) over ()
    , b.item_type
    , isnull(a.sales, 0)
    , isnull(a.avg_price, 0)
    , isnull(a.profit, 0)
FROM 
    (SELECT [year], [quarter], [item_type], [sales], [avg price], [profit] 
    FROM sales_table) a
FULL OUTER JOIN
    (SELECT item_type FROM item_table) b
ON a.item_type = b.item_type
ORDER BY a.year, a.quarter, b.item_type

答案 1 :(得分:0)

让它发挥作用。

关键是将Item_type与日期交叉连接(对于此示例,需要创建临时日历表),然后使用sales_table和profit_table的计算结果进行左连接。

insert into #date_table values
(2010,'Q1'),(2010,'Q2'), (2010,'Q3'),(2010,'Q4');

SELECT 
    b.yr
  , b.qtr
  , b.item_type
  , COALESCE(MAX(a.sales),0) AS sales
  , COALESCE(MAX(a.avg_price),0) AS avg_price
  , COALESCE(MAX(a.profit),0) AS profit
FROM 
  (
    SELECT 
       dt.[yr]
      ,dt.[qtr]
      ,CASE
        WHEN it.[item_type] IN ('mno', 'xyz') THEN 'Other'
        ELSE UPPER(it.[item_type])
       END AS [item_type]
    FROM 
      #date_table AS dt
    CROSS JOIN 
      #item_table AS it
    WHERE 
      dt.[yr] >=2010
    GROUP BY 
      dt.[yr]
      ,dt.[qtr]
      ,CASE
        WHEN it.[item_type] IN ('mno', 'xyz') THEN 'Other'
        ELSE UPPER(it.[item_type])
       END
  ) AS b
LEFT JOIN
  (SELECT [yr], [qtr], 
     CASE
      WHEN item_type IN ('mno', 'xyz') THEN 'Other'
      ELSE UPPER([item_type])
     END AS [item_type], 
     COUNT(sale_price) OVER (PARTITION BY yr, qtr, item_type) [sales], 
     AVG(sale_price) OVER (PARTITION BY yr, qtr, item_type) [avg_price],
     NULL [profit] 
   FROM #sales_table
   WHERE yr >=2010
   UNION ALL
   SELECT yr, qtr, 
     CASE
      WHEN item_type IN ('mno', 'xyz') THEN 'Other'
      ELSE UPPER([item_type])
     END AS [item_type], 
     NULL [sales], 
     NULL [avg_price],
     SUM(profit) OVER (PARTITION BY yr, qtr, item_type) [profit] 
   FROM #profit_table
   WHERE yr >=2010
  ) a
    ON
      a.[yr] = b.[yr]
      AND
      a.[qtr] = b.[qtr]
      AND
      a.[item_type] = b.[item_type]
GROUP BY
  b.yr, b.qtr, b.item_type
ORDER BY b.yr, b.qtr, b.item_type;