我通过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
请指教。
干得好。正如评论中描述的那样。
我制作了一个迷你日历表,但你会花一些时间制作一个真正的日历表。一旦你拥有它,你将一直使用它。
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 |
+------+-----+-----------+-------+-----------+--------+