在SQL查询输出中包含0或NULL的行

问题描述 投票:0回答:1

我通过2个不同查询的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 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
FULL OUTER JOIN
   (SELECT      
      CASE WHEN item_type IN ('mno', 'xyz') THEN 'Other' else upper(item_type) 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

请指教。

sql-server
1个回答
2
投票

干得好。正如评论中描述的那样。

我制作了一个迷你日历表,但你会花一些时间制作一个真正的日历表。一旦你拥有它,你将一直使用它。

    if OBJECT_ID('tempdb..#sales_table', 'U') is not null
      drop table #sales_table
    if OBJECT_ID('tempdb..#profit_table', 'U') is not null
      drop table #profit_table
    if OBJECT_ID('tempdb..#item_table', 'U') is not null
      drop table #item_table
    if OBJECT_ID('tempdb..#date_table', 'U') is not null
      drop table #date_table

    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)
    );

    create table #date_table
    (
        [yr] int
      , [qtr] varchar(2)
    );

    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');

    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;

结果:

+------+-----+-----------+-------+-----------+--------+
|  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     |     1 |        12 |     23 |
| 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     |     1 |        92 |     15 |
| 2010 | Q3  | ABC       |     0 |         0 |      0 |
| 2010 | Q3  | DEF       |     0 |         0 |      0 |
| 2010 | Q3  | GHI       |     0 |         0 |      0 |
| 2010 | Q3  | JKL       |     0 |         0 |      0 |
| 2010 | Q3  | Other     |     0 |         0 |      0 |
| 2010 | Q4  | ABC       |     0 |         0 |      0 |
| 2010 | Q4  | DEF       |     0 |         0 |      0 |
| 2010 | Q4  | GHI       |     0 |         0 |      0 |
| 2010 | Q4  | JKL       |     0 |         0 |      0 |
| 2010 | Q4  | Other     |     0 |         0 |      0 |
+------+-----+-----------+-------+-----------+--------+
© www.soinside.com 2019 - 2024. All rights reserved.