【问题标题】:SQL multiple SUM with conditions in a single querySQL 多个 SUM 与单个查询中的条件
【发布时间】:2019-11-28 03:13:06
【问题描述】:

在 Laravel 应用程序上工作,我需要从第二个数据库中检索数据,这就是为什么我有一个像这样的特殊“DB”: DB::connection('sqlsrv2')。 在这个数据库中,有一个表 customerAccount 和一个表 Opportunity。 我们想知道我们每个月创造了多少机会,赢得或失去了多少机会,以及为一个精确的年份和一个精确的客户家庭。 我可以通过一些 foreach 和每个案例的查询来检索数据(新的、赢得或失去的机会),但最终每个客户和每个月都会有超过 12700 个查询。

所以我想到了 SQL SUM,并且我可以在一个 (looong) 查询中完成它,该查询将创建 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”。

【问题讨论】:

  • 您希望如何用日期(然后是机会.OpportunityCloseDate)值求和?
  • 我没有,我想总结案件发生的次数。我应该用then 1 替换then opportunity.OpportunityDate 吗?
  • 是的。您应该将日期替换为值 1
  • 我不确定raw 方法是否支持将 PHP 变量作为 SQL 语句的一部分。将 $year 更改为 '$year'$month$family)或使用占位符使用参数化查询。

标签: sql sql-server laravel-5 sum


【解决方案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。

【讨论】:

    【解决方案2】:

    删除 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 作为建议使用组

    【讨论】:

    • 谢谢,既然你提到了,我看到 $family 没有通过,所以我也在它周围添加了单引号:'$family'
    • 每个字符串 var 必须用单引号括起来 .. (如果您使用的 var 是字符串或数字,我显然无法想象 .. )但是如果 db 中的值是数字不要使用单引号..
    【解决方案3】:

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

    但是,有几个问题:

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

    【讨论】:

    • 谢谢,我用这些建议编辑了我的问题,遗憾的是我仍然有一个错误。
    【解决方案4】:

    好的,找到诀窍了。 Laravel 查询生成器会在您的原始查询之后自动添加 'from' 语句。所以我添加了一个双“来自”,以及我的加入和在它之前写的条件。我改用构建器的方法并将查询转换为:

    $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();
    

    而且它有效!谢谢大家。

    【讨论】:

      猜你喜欢
      • 2020-06-11
      • 2022-01-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多