PHP/SQL select 基于求和结果
PHP/SQL select based on sum result
我很难根据总和来限制我的查询结果。示例代码:
$rows = Entry::find()
->section('cities')
->select('state')
->having("sum(case when covered = '1' then 1 else 0 end) = 0")
->asArray()
->all();
我只想 select 个“覆盖”了 0 个城市的州。 运行 我在“有”行上方的代码似乎被忽略了(它包括零和非零情况)。我尝试使用“where”而不是“having”,但它会导致 PDOException - “无效使用组函数”。我认为“拥有”是正确的方法,但我犯了一个新手错误——有什么提示吗?
/*** 更新 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("numCovered = 0")
/*** 更新 2 ***/
尽管有 numCovered = 19
,但使用 @cpalmer 建议的简化测试用例仍然会导致“CA”被 selected。我现在想知道这是否是 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 发布的数据库 Fiddle 所建议的,我的 sql 应该 工作。转储原始 sql 表明 having
行被忽略。问题可能出在 CraftCMS/Yii 和我对环境缺乏了解。
尝试为状态添加一个 groupBy()
$rows = Entry::find()
->section('cities')
->select('state')
->groupBy('state')
->having("sum(case when covered = '1' then 1 else 0 end) = 0")
->asArray()
->all();
尝试从 select 编辑的列中删除 'covered'。在某些 SQL 数据库中,当您对数据进行分组时,仅在 select 语句中有一个不在 group by 语句或聚合中的列可能会导致错误。对于您的情况,我认为此专栏会导致意外结果。如果你真的想包含它,把它扔进一个聚合中并给它起别名,比如 '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();
尝试输入 having 部分“numCovered = 0”。
首先:我完全支持@Olivier,您应该将问题的 SQL 部分与体系结构本身分离。对于 SQL 部分,重要的是让其他人知道您使用的是哪个数据库或 SQL 方言(MySQL、PostgreSQL、MsSQL...) .
只是猜测 MySQL
您正在使用什么:
这两种方式实际上都应该有效,重复查询部分以按名称
拥有或引用它
如果两者都不起作用,并且您想在没有 having
的情况下工作,也许您可以实现子选择?
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
嗯,我猜你忘记了 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();
我很难根据总和来限制我的查询结果。示例代码:
$rows = Entry::find()
->section('cities')
->select('state')
->having("sum(case when covered = '1' then 1 else 0 end) = 0")
->asArray()
->all();
我只想 select 个“覆盖”了 0 个城市的州。 运行 我在“有”行上方的代码似乎被忽略了(它包括零和非零情况)。我尝试使用“where”而不是“having”,但它会导致 PDOException - “无效使用组函数”。我认为“拥有”是正确的方法,但我犯了一个新手错误——有什么提示吗?
/*** 更新 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("numCovered = 0")
/*** 更新 2 ***/
尽管有 numCovered = 19
,但使用 @cpalmer 建议的简化测试用例仍然会导致“CA”被 selected。我现在想知道这是否是 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 发布的数据库 Fiddle 所建议的,我的 sql 应该 工作。转储原始 sql 表明 having
行被忽略。问题可能出在 CraftCMS/Yii 和我对环境缺乏了解。
尝试为状态添加一个 groupBy()
$rows = Entry::find()
->section('cities')
->select('state')
->groupBy('state')
->having("sum(case when covered = '1' then 1 else 0 end) = 0")
->asArray()
->all();
尝试从 select 编辑的列中删除 'covered'。在某些 SQL 数据库中,当您对数据进行分组时,仅在 select 语句中有一个不在 group by 语句或聚合中的列可能会导致错误。对于您的情况,我认为此专栏会导致意外结果。如果你真的想包含它,把它扔进一个聚合中并给它起别名,比如 '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();
尝试输入 having 部分“numCovered = 0”。
首先:我完全支持@Olivier,您应该将问题的 SQL 部分与体系结构本身分离。对于 SQL 部分,重要的是让其他人知道您使用的是哪个数据库或 SQL 方言(MySQL、PostgreSQL、MsSQL...) .
只是猜测 MySQL
您正在使用什么:
这两种方式实际上都应该有效,重复查询部分以按名称
如果两者都不起作用,并且您想在没有 having
的情况下工作,也许您可以实现子选择?
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
嗯,我猜你忘记了 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();