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 查询给我以下内容:

  1. 授予的数量 - 授予的合同金额和状态的总和
  2. 中奖人数 - inviteTable.status=中奖人数
  3. 被报价的数量 - quoteAmount 和授予的状态的总和
  4. 引用次数 - 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

http://sqlfiddle.com/#!9/ddaac/14

不幸的是您的架构;如果您只有一个 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