mysql 图表子查询
mysql subquery for charts
我有 2 个表,其中包含以下数据
邀请表
inviteDate | contractAmount | status
2014-01-01 1500 awarded
2015-01-01 2000 awarded
2015-01-02 4000 closed
2015-02-01 6000 awarded
2015-02-02 8000 awarded
2015-03-01 8500 awarded
报价表
quoteDate | quoteAmount | status
2014-03-01 1500 awarded
2015-01-02 2000 awarded
2015-01-03 4000 sent
2015-01-04 6000 awarded
2015-02-03 8000 awarded
2015-02-10 8500 sent
2015-02-11 9000 awarded
2015-03-01 9500 awarded
我想进行 ONE 查询,得到以下数据结构
month | quotedTotal | quotedCount | awardedTotal | awardedCount
January 8000 2 2000 1
February 17000 2 14000 2
March 9500 1 8500 1
目前我已经编写了这段代码...但是它不起作用
SELECT
MONTHNAME(t1.due_date) as month,
(select sum(`amount`) from quoteTable where awarded= 1 ) as estimatedAmount,
sum(t1.contactAmount) AS sumContactAmount,
COUNT(*) as `noOfAwarded`
FROM inviteTable t1
where
t1.status = "Awarded" and
t1.inviteDate between '2014-11-01' and '2015-10-31'
GROUP BY MONTH(due_date)
;
基本上我想要 ONE 查询给我以下内容:
- 授予的数量 - 授予的合同金额和状态的总和
- 中奖人数 - inviteTable.status=中奖人数
- 被报价的数量 - quoteAmount 和授予的状态的总和
- 引用次数 - quotedTable.status=获奖次数
全部按月份和日期范围分组
我的查询无效。我被困住了,非常感谢您的帮助!
这里有一个方法可以做到,请注意,您在两个 table 中都有日期,并且您最好使用 join left join
,这样可以确保出现在 left join
中的日期left table 在这种情况下总是返回月份名称。
select
t1.month,
t1.awardedTotal,
t1.awardedCount,
t2.quotedTotal,
t2.quotedCount
from(
select
monthname(t1.inviteDate) as month,
month(t1.inviteDate) as m,
sum(
case
when t1.status = 'awarded' then t1.contractAmount else 0
end
) as awardedTotal,
sum(
case
when t1.status = 'awarded' then 1 else 0
end
) as awardedCount
from inviteTable t1
where t1.inviteDate between '2014-11-01' and '2015-10-31'
group by month
)t1
left join(
select
monthname(t2.quoteDate) as month,
sum(
case
when t2.status = 'awarded' then t2.quoteAmount else 0
end
) as quotedTotal,
sum(
case
when t2.status = 'awarded' then 1 else 0
end
) as quotedCount
from quoteTable t2
where t2.quoteDate between '2014-11-01' and '2015-10-31'
group by month
)t2 on
t1.month = t2.month
order by t1.m
http://sqlfiddle.com/#!9/a863a/10
更新:
是的,因为您希望日期同时出现在两个 table 中,所以无法通过上述过程完成,因为它始终将一个 table 视为左侧 table 并将从该 [=] 中获取所有日期23=]。要获取两个 table 中所有日期的数据,您首先需要从两个 table 中获取日期,然后使用左连接将计算部分作为
select
t1.month,
coalesce(t2.awardedTotal,0) as awardedTotal,
coalesce(t2.awardedCount,0) as awardedCount,
coalesce(t3.quotedTotal,0) as quotedTotal,
coalesce(t3.quotedCount,0) as quotedCount
from(
select month(inviteDate) as m,monthname(inviteDate) as month
from inviteTable where inviteDate between '2014-11-01' and '2015-10-31'
union
select month(quoteDate) as m,monthname(quoteDate) as month
from quoteTable where quoteDate between '2014-11-01' and '2015-10-31'
)t1
left join(
select
monthname(inviteDate) as month,
sum(
case
when status = 'awarded' then contractAmount else 0
end
) as awardedTotal,
sum(
case
when status = 'awarded' then 1 else 0
end
) as awardedCount
from inviteTable
group by month
)t2 on t1.month = t2.month
left join(
select
monthname(quoteDate) as month,
sum(
case
when status = 'awarded' then quoteAmount else 0
end
) as quotedTotal,
sum(
case
when status = 'awarded' then 1 else 0
end
) as quotedCount
from quoteTable
group by month
)t3 on t1.month=t3.month
order by t1.m
不幸的是您的架构;如果您只有一个 table 并有一个额外的列来记录您拥有的记录类型,那会更容易。但是,如果您首先通过 union all
将两个 table 收集到一个 table 中,您可以使用相当简单的查询来生成所需的结果:
select
monthname(_date) month,
sum(quoteAwarded * amount) quotedTotal,
sum(quoteAwarded) quotedCount,
sum(contractAwarded * amount) awardedTotal,
sum(contractAwarded) awardedCount
from (select inviteDate _date, contractAmount amount, status = 'awarded' contractAwarded, 0 quoteAwarded from inviteTable
union all
select quoteDate, quoteAmount, 0, status = 'awarded' from quoteTable) x
where _date between '2014-11-01' and '2015-10-31'
group by 1
order by month(_date)
查看 SQLFiddle 使用您的样本数据,并产生您预期的输出。
这个查询的核心是一个方便的事实,即(在 mysql 中)"true" 是 1,"false" 是 0 - 允许使用 sum()
count()
,更重要的是通过在一些简单的数学运算中使用 sum()
来避免使用 case
。
我有 2 个表,其中包含以下数据
邀请表
inviteDate | contractAmount | status
2014-01-01 1500 awarded
2015-01-01 2000 awarded
2015-01-02 4000 closed
2015-02-01 6000 awarded
2015-02-02 8000 awarded
2015-03-01 8500 awarded
报价表
quoteDate | quoteAmount | status
2014-03-01 1500 awarded
2015-01-02 2000 awarded
2015-01-03 4000 sent
2015-01-04 6000 awarded
2015-02-03 8000 awarded
2015-02-10 8500 sent
2015-02-11 9000 awarded
2015-03-01 9500 awarded
我想进行 ONE 查询,得到以下数据结构
month | quotedTotal | quotedCount | awardedTotal | awardedCount
January 8000 2 2000 1
February 17000 2 14000 2
March 9500 1 8500 1
目前我已经编写了这段代码...但是它不起作用
SELECT
MONTHNAME(t1.due_date) as month,
(select sum(`amount`) from quoteTable where awarded= 1 ) as estimatedAmount,
sum(t1.contactAmount) AS sumContactAmount,
COUNT(*) as `noOfAwarded`
FROM inviteTable t1
where
t1.status = "Awarded" and
t1.inviteDate between '2014-11-01' and '2015-10-31'
GROUP BY MONTH(due_date)
;
基本上我想要 ONE 查询给我以下内容:
- 授予的数量 - 授予的合同金额和状态的总和
- 中奖人数 - inviteTable.status=中奖人数
- 被报价的数量 - quoteAmount 和授予的状态的总和
- 引用次数 - quotedTable.status=获奖次数
全部按月份和日期范围分组
我的查询无效。我被困住了,非常感谢您的帮助!
这里有一个方法可以做到,请注意,您在两个 table 中都有日期,并且您最好使用 join left join
,这样可以确保出现在 left join
中的日期left table 在这种情况下总是返回月份名称。
select
t1.month,
t1.awardedTotal,
t1.awardedCount,
t2.quotedTotal,
t2.quotedCount
from(
select
monthname(t1.inviteDate) as month,
month(t1.inviteDate) as m,
sum(
case
when t1.status = 'awarded' then t1.contractAmount else 0
end
) as awardedTotal,
sum(
case
when t1.status = 'awarded' then 1 else 0
end
) as awardedCount
from inviteTable t1
where t1.inviteDate between '2014-11-01' and '2015-10-31'
group by month
)t1
left join(
select
monthname(t2.quoteDate) as month,
sum(
case
when t2.status = 'awarded' then t2.quoteAmount else 0
end
) as quotedTotal,
sum(
case
when t2.status = 'awarded' then 1 else 0
end
) as quotedCount
from quoteTable t2
where t2.quoteDate between '2014-11-01' and '2015-10-31'
group by month
)t2 on
t1.month = t2.month
order by t1.m
http://sqlfiddle.com/#!9/a863a/10
更新: 是的,因为您希望日期同时出现在两个 table 中,所以无法通过上述过程完成,因为它始终将一个 table 视为左侧 table 并将从该 [=] 中获取所有日期23=]。要获取两个 table 中所有日期的数据,您首先需要从两个 table 中获取日期,然后使用左连接将计算部分作为
select
t1.month,
coalesce(t2.awardedTotal,0) as awardedTotal,
coalesce(t2.awardedCount,0) as awardedCount,
coalesce(t3.quotedTotal,0) as quotedTotal,
coalesce(t3.quotedCount,0) as quotedCount
from(
select month(inviteDate) as m,monthname(inviteDate) as month
from inviteTable where inviteDate between '2014-11-01' and '2015-10-31'
union
select month(quoteDate) as m,monthname(quoteDate) as month
from quoteTable where quoteDate between '2014-11-01' and '2015-10-31'
)t1
left join(
select
monthname(inviteDate) as month,
sum(
case
when status = 'awarded' then contractAmount else 0
end
) as awardedTotal,
sum(
case
when status = 'awarded' then 1 else 0
end
) as awardedCount
from inviteTable
group by month
)t2 on t1.month = t2.month
left join(
select
monthname(quoteDate) as month,
sum(
case
when status = 'awarded' then quoteAmount else 0
end
) as quotedTotal,
sum(
case
when status = 'awarded' then 1 else 0
end
) as quotedCount
from quoteTable
group by month
)t3 on t1.month=t3.month
order by t1.m
不幸的是您的架构;如果您只有一个 table 并有一个额外的列来记录您拥有的记录类型,那会更容易。但是,如果您首先通过 union all
将两个 table 收集到一个 table 中,您可以使用相当简单的查询来生成所需的结果:
select
monthname(_date) month,
sum(quoteAwarded * amount) quotedTotal,
sum(quoteAwarded) quotedCount,
sum(contractAwarded * amount) awardedTotal,
sum(contractAwarded) awardedCount
from (select inviteDate _date, contractAmount amount, status = 'awarded' contractAwarded, 0 quoteAwarded from inviteTable
union all
select quoteDate, quoteAmount, 0, status = 'awarded' from quoteTable) x
where _date between '2014-11-01' and '2015-10-31'
group by 1
order by month(_date)
查看 SQLFiddle 使用您的样本数据,并产生您预期的输出。
这个查询的核心是一个方便的事实,即(在 mysql 中)"true" 是 1,"false" 是 0 - 允许使用 sum()
count()
,更重要的是通过在一些简单的数学运算中使用 sum()
来避免使用 case
。