基于求和结果的php/sql选择

jogvjijk  于 2021-07-24  发布在  Java
关注(0)|答案(5)|浏览(279)

我很难根据总和限制查询结果。示例代码:

$rows = Entry::find()
      ->section('cities')
      ->select('state')
      ->having("sum(case when covered = '1' then 1 else 0 end) = 0")
      ->asArray()
      ->all();

我只想选择0个城市“覆盖”的州。在“having”行上运行代码似乎被忽略了(它包括零和非零情况)。我试着用“where”代替“having”,但结果出现了一个异常——“组函数的使用无效”。我认为“拥有”是正确的方法,但是我犯了一个新手的错误——有什么建议吗?
/更新1/
谢谢@scaisedge和@angelm的提示-- groupBy 有帮助,但仍然没有按预期工作。似乎“拥有”一词仍然被忽视。修改代码:

$test = Entry::find()
      ->section('cities')
      ->select(['state', 'covered', "sum(case when covered = '1' then 1 else 0 end) as numCovered"])
      ->groupBy('state')
      ->having("sum(case when covered = '1' then 1 else 0 end) = 0")
      ->asArray()
      ->all();

我记录以下结果:

{state: "AL", covered: "0", numCovered: "0"}
{state: "AK", covered: "0", numCovered: "0"}
{state: "CA", covered: "1", numCovered: "19"}
{state: "CO", covered: "0", numCovered: "0"}
...

如上所示,当numcovered显然不是0时,状态(ca)也包括在内。
我还尝试了以下“having”代码(我假设是相同的): ->having("numCovered = 0") /更新2/
使用@cpalmer建议的简化测试用例仍然会导致“ca”被选中,尽管有 numCovered = 19 . 我现在想知道这是否是craft cms的一个特性,因为我的查询似乎是正确的?

$test = Entry::find()
      ->section('cities')
      ->select('state')
      ->groupBy('state')
      ->having("sum(case when covered = '1' then 1 else 0 end) = 0")
      ->asArray()
      ->all();

有没有一种方法可以不用 having ?
/更新3/
正如@pocketrocket发布的db fiddle所建议的,我的sql应该可以工作。转储原始sql表明 having 忽略行。这个问题很可能与我对环境缺乏了解有关。

iyr7buue

iyr7buue1#

首先:我完全支持@olivier,您应该将问题的sql部分与体系结构本身分离。对于sql部分,让其他人知道您使用的是哪个数据库或sql方言(mysql、postgresql、mssql…)很重要。
我猜是的 MySQL 您正在使用什么:这两种方法实际上都应该起作用,按照user126587的建议,重复querypart中的have或按名称引用它
如果两者都不起作用,而你又不想工作 having 也许你可以实现一个subselect?

SELECT 
    state, 
    sum(case when covered = '1' then 1 else 0 end) as numCovered 
FROM cities 
GROUP BY state
HAVING sum(case when covered = '1' then 1 else 0 end) = 0;

SELECT 
    state, 
    sum(case when covered = '1' then 1 else 0 end) as numCovered 
FROM cities 
GROUP BY state
HAVING numCovered = 0;

SELECT * FROM (
  SELECT 
      state, 
      sum(case when covered = '1' then 1 else 0 end) as numCovered 
  FROM cities 
  GROUP BY state
) sub_select
WHERE sub_select.numCovered = 0;

你可以在这里玩:db fiddle link

34gzjxbg

34gzjxbg2#

尝试为state添加groupby()

$rows = Entry::find()
  ->section('cities')
  ->select('state')
  ->groupBy('state')
  ->having("sum(case when covered = '1' then 1 else 0 end) = 0")
  ->asArray()
  ->all();
l7wslrjt

l7wslrjt3#

请尝试从所选列中删除“covered”。在某些sql数据库中,对数据进行分组时,如果select语句中有一列不在GROUPBY语句或聚合中,则可能会导致错误。在你的情况下,我认为这篇专栏文章造成了意想不到的结果。如果你真的想包含它,把它放到一个聚合中并给它取别名,比如 'MAX(covered) as covered' ```
$test = Entry::find()
->section('cities')
->select(['state', "sum(case when covered = '1' then 1 else 0 end) as numCovered"])
->groupBy('state')
->having("sum(case when covered = '1' then 1 else 0 end) = 0")
->asArray()
->all();

rdlzhqv9

rdlzhqv94#

尝试输入having部分“numcovered=0”。

s2j5cfk0

s2j5cfk05#

我猜你忘记了having子句中0的一个引号。

$test = Entry::find()
  ->section('cities')
  ->select('state')
  ->groupBy('state')
  ->having("sum(case when covered = '1' then 1 else 0 end) = '0'")
  ->asArray()
  ->all();

相关问题