我有一个包含以下字段的表:
公司 水果 日期 数量 价钱 TOTAL_PRICE
我有一个总结数据的查询:
Person per= (Person) criteria.uniqueResult();
per.setCreatedOn("crtBy");
currentSession.merge(per);
如果某个公司一年没有数据,我将如何将虚拟行包含在输出中?在我的时间框架内的四分之一?
答案 0 :(得分:0)
这有点复杂,所以让我引导你完成它。首先,您需要一个公司列表,包括没有购买的公司。您可以通过以下方式获得:
SELECT DISTINCT company
FROM fruit_paid;
您可以使用它来获取所有公司的摘要,所有这些都是这样的:
WITH
company_names as
(SELECT DISTINCT company
FROM fruit_paid)
SELECT company_names.company, sum(fruit_paid.qty) as total_fruit_purchased
FROM company_names
LEFT OUTER JOIN fruit_paid
ON company_names.company = fruit_paid.company
GROUP BY company_names.company;
那里有两件事情:1-我采取之前的查询(" SELECT DISTINCT ...
"),并将其称为公共表表达式 - 它只是意味着我可以像表一样使用该查询。 2-我使用LEFT OUTER JOIN
,它将使用左表定义行,并从右表中加入所有内容。
这是完成这项工作所需要的核心。您可以使用generate_series
函数获取年份列表。类似的东西:
SELECT extract(YEAR from generate_series) as year
FROM generate_series('2015-01-01'::date,
'2016-01-01'::date,
'1 year');
您可以转身并添加到上一个查询:
WITH
company_names as
(SELECT DISTINCT company
FROM fruit_paid),
years as
(SELECT extract(YEAR from generate_series) as year
FROM generate_series('2015-01-01'::date,
'2016-01-01'::date,
'1 year'))
SELECT company_names.company,
years.year,
sum(fruit_paid.qty) as total_fruit_purchased
FROM company_names
CROSS JOIN years
LEFT OUTER JOIN fruit_paid
ON company_names.company = fruit_paid.company
AND extract(YEAR from fruit_paid.date) = years.year
GROUP BY company_names.company, years.year;
使用CROSS JOIN
,左表(company_names
)和右表(years
)的每个组合可以获得一行。换句话说,每个公司和年份一行,无论购买。您再次与fruit_paid联系以获取购买数据。
最后一块是宿舍。获得所有季度的列表是一种简单的方法:
VALUES ('Q1'), ('Q2'), ('Q3'), ('Q4');
所以,让我们加入:
WITH
company_names as
(SELECT DISTINCT company
FROM fruit_paid),
years as
(SELECT extract(YEAR from generate_series) as year
FROM generate_series('2015-01-01'::date,
'2016-01-01'::date,
'1 year')),
quarters (quarter) as
(VALUES ('Q1'), ('Q2'), ('Q3'), ('Q4'))
SELECT company_names.company,
years.year,
quarters.quarter,
sum(fruit_paid.qty) as total_fruit_purchased
FROM company_names
CROSS JOIN years
CROSS JOIN quarters
LEFT OUTER JOIN fruit_paid
ON company_names.company = fruit_paid.company
AND extract(YEAR from fruit_paid.date) = years.year
AND quarters.quarter = case
WHEN extract(MONTH FROM date) <= 3
THEN 'Q1'
WHEN extract(MONTH FROM date) BETWEEN 4 AND 6
THEN 'Q2'
WHEN extract(MONTH FROM date) BETWEEN 7 AND 9
THEN 'Q3'
WHEN extract(MONTH FROM date) BETWEEN 10 AND 12
THEN 'Q4'
ELSE 'UNKNOWN'
END
GROUP BY company_names.company, years.year, quarters.quarter;
我们在这里做的唯一新奇事情是为quarters
公用表表达式提供更多定义 - 我们添加了一个列名。对于像VALUES
这样的伪查询,能够为返回的列定义名称是很方便的,并且它使得查询稍后可以理解(否则我们将加入{{1 ,这很难理解。)
希望有所帮助。
以下是一些相关文档:
quarters.column
。