SQL在单个查询中具有条件的多个SUM

时间:2019-07-19 07:00:34

标签: sql sql-server laravel-5 sum

在Laravel应用程序上工作时,我需要从第二个数据库中检索数据,这就是为什么我有一个特殊的“ DB”,例如:         DB::connection('sqlsrv2')。 在此数据库上,有一个表customerAccount和一个表Opportunity。         我们想知道我们每个月以及对于精确的一年和精确的客户家庭而言,创造,赢得或失去的机会是多少。 我可以使用一些foreach以及每种情况的查询(新的,成功的或失败的机会)来检索数据,但最终却要为每个客户和每个月进行一次> 12700次查询。

因此,我想到了SQL SUM,我可以在一个(长)查询中创建3列(新列,成功列,丢失列)来完成此操作。然后,我将对所选年份的每个月重复查询。 问题是,我不记得该怎么做,并且因为我真的不知道要搜索什么,所以找不到任何帮助。

这是我写查询的错误尝试:[编辑后在评论中进行建议]

$clients = DB::connection('sqlsrv2')->table('customerAccount')
        ->select(DB::connection('sqlsrv2')->raw(
            "customerAccount.Name, 
  SUM(case when opportunity.customerAccountId = customerAccount.Id
  and YEAR(opportunity.OpportunityDate) = $year
  and MONTH(opportunity.OpportunityDate) = $month
  then 1
  else 0
  end) as nbOppNew,
  SUM(case when opportunity.customerAccountId = customerAccount.Id
  and YEAR(opportunity.OpportunityCloseDate) = $year
  and MONTH(opportunity.OpportunityCloseDate) = $month
  and StageProbability = 99
  then 1
  else 0
  end) as nbOppWon,
  SUM(case when opportunity.customerAccountId = customerAccount.Id
  and YEAR(opportunity.OpportunityCloseDate) = $year
  and MONTH(opportunity.OpportunityCloseDate) = $month
  and StageProbability <= 1
  then 1
  else 0
  end) as nbOppLost
  FROM
  customerAccount
  INNER JOIN opportunity ON customerAccount.Id = opportunity.customerAccountId
  WHERE
  MainInvoicingAddress_CountryIsoCode = 'ES'
  and familyId = '$family'
  GROUP BY customerAccount.Name"
        ))
        ->get();

Laravel生成的错误:SQLSTATE[42000]: [Microsoft][SQL Server Native Client 11.0][SQL Server]Incorrect syntax near 'from'.

我真正想要得到的是一个带有客户端名称的数组,每个数组的名称分别是:第二个条目“ nbOppNew”,其中包含SUM值。第三个是“ nbOppWon”,然后第四个是“ nbOppLost”。

4 个答案:

答案 0 :(得分:1)

您的错误可能是由于第一列的select语句中的单引号引起的。删除引号,就不会发生错误。

       "SELECT customerAccount.Name,
  SUM(case when opportunity.customerAccountId = customerAccount.Id
  and YEAR(opportunity.OpportunityDate) = $year
  and MONTH(opportunity.OpportunityDate) = $month
  then opportunity.OpportunityDate

还要在分组依据中的选择中使用非汇总列(名称)。您正在根据 id 进行分组。如果需要基于ID进行分组,请在select语句中使用ID。

答案 1 :(得分:1)

删除customerAccount.Name的单引号,并使用ES值的单引号

     "SELECT customerAccount.Name,
      SUM(case when opportunity.customerAccountId = customerAccount.Id
      and YEAR(opportunity.OpportunityDate) = $year
      and MONTH(opportunity.OpportunityDate) = $month
      then opportunity.OpportunityDate
      else 0
      end) as nbOppNew,
      SUM(case when opportunity.customerAccountId = customerAccount.Id
      and YEAR(opportunity.OpportunityCloseDate) = $year
      and MONTH(opportunity.OpportunityCloseDate) = $month
      and StageProbability = 99
      then opportunity.OpportunityDate
      else 0
      end) as nbOppWon,
      SUM(case when opportunity.customerAccountId = customerAccount.Id
      and YEAR(opportunity.OpportunityCloseDate) = $year
      and MONTH(opportunity.OpportunityCloseDate) = $month
      and StageProbability <= 1
      then opportunity.OpportunityCloseDate
      else 0
      end) as nbOppLost
      FROM
      customerAccount
      INNER JOIN opportunity ON customerAccount.Id = opportunity.customerAccountId
      WHERE
      MainInvoicingAddress_CountryIsoCode = 'ES'
      and familyId = $family
      GROUP BY customerAccount.Name"

并根据customerAccount.Name建议使用分组

答案 2 :(得分:1)

以您编写查询的方式,没有实际的语法错误。因此,我希望这与查询中单引号的转义有关。但是查询本身可以很好地执行。

但是,问题很少:

  • 日期值上的SUM可疑,并且很可能应该重做,因为您不允许对日期求和
  • GROUP BYID的代表,而您尝试选择Name

答案 3 :(得分:1)

好的,找到了窍门。 Laravel Query Builder会在原始查询之后自动添加“ from”语句。因此,我添加了一个双“ from”,并在其之前添加了join和where条件。我改用了构建器的方法,并将查询转换为:

$clients = DB::connection('sqlsrv2')->table('customerAccount')
        ->select(DB::connection('sqlsrv2')->raw(
            "customerAccount.Name, 
  SUM(case when opportunity.customerAccountId = customerAccount.Id
  and YEAR(opportunity.OpportunityDate) = $year
  and MONTH(opportunity.OpportunityDate) = $month
  then 1
  else 0
  end) as nbOppNew,
  SUM(case when opportunity.customerAccountId = customerAccount.Id
  and YEAR(opportunity.OpportunityCloseDate) = $year
  and MONTH(opportunity.OpportunityCloseDate) = $month
  and StageProbability = 99
  then 1
  else 0
  end) as nbOppWon,
  SUM(case when opportunity.customerAccountId = customerAccount.Id
  and YEAR(opportunity.OpportunityCloseDate) = $year
  and MONTH(opportunity.OpportunityCloseDate) = $month
  and StageProbability <= 1
  then 1
  else 0
  end) as nbOppLost"
        ))
            ->join('opportunity', 'customerAccount.Id', '=', 'opportunity.customerAccountId')
            ->where('MainInvoicingAddress_CountryIsoCode', 'ES')
            ->where('familyId', $family)
            ->groupBy('customerAccount.Name')
        ->get();

它有效!谢谢大家。