MySQL 到 PostgreSQL - 在数组中查找并计算数组值
Posted
技术标签:
【中文标题】MySQL 到 PostgreSQL - 在数组中查找并计算数组值【英文标题】:MySQL to PostgreSQL - Find in array, and count array values 【发布时间】:2021-02-10 11:51:20 【问题描述】:我有一个colors
表和一个items
表,这两个表之间存在多对多 关系(通过items_colors
表)。一种物品可以有多种颜色,一种颜色可以有多种物品。
items
id
colors
id
name
items_colors
item_id [foreign key: items(id)]
color_id [foreign key: colors(id)]
我目前正在从 MySQL 迁移到 PostgreSQL。下面的这个 SQL 查询在 mysql 上运行良好,但我无法让它在 PostgreSQL 上运行:
SELECT i.*
FROM
items i
JOIN items_colors ic ON ic.item_id = i.id
JOIN colors c ON c.id = ic.color_id
GROUP BY i.id
HAVING COUNT(*) = SUM( c.name IN ('green', 'blue') )
A 也尝试用不同的方式表达HAVING
:
HAVING SUM( c.name NOT IN ('green', 'blue') ) = 0;
在所有情况下,使用 PostgreSQL 我都会收到此错误:
Query 1 ERROR: ERROR: function sum(boolean) does not exist
LINE 7: HAVING COUNT(*) = SUM( c.name IN ('green'...
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
(仅出于此查询的上下文和目标,我想获取所有仅匹配一种或多种提供的颜色(来自提供的颜色数组)的项目。如果item 还与数组中未指定的附加颜色相关联,不应检索它。在上面的示例中,我得到 all 与给定数组匹配的项目,因此所有具有绿色,或蓝色,或绿色和蓝色。但是如果一个项目既有蓝色也有红色(或只有红色,或没有颜色),它将被排除在结果之外。 )
【问题讨论】:
【参考方案1】:这应该在 Postgres 中工作,假设 items.id
是主键:
SELECT i.*
FROM items i JOIn
items_colors ic
ON ic.item_id = i.id JOIN
colors c
ON c.id = ic.color_id
GROUP BY i.id
HAVING COUNT(*) = SUM( (c.name IN ('green', 'blue'))::INT );
或者:
HAVING COUNT(*) = COUNT(*) FILTER (WHERE c.name IN ('green', 'blue'))
适用于两个数据库的版本是:
HAVING COUNT(*) = SUM(CASE WHEN c.name IN ('green', 'blue') THEN 1 ELSE 0 END);
【讨论】:
非常感谢您的帮助。它现在运行良好,我正在学习更好地使用 PostgreSQL!【参考方案2】:我会看看 PostgreSQL 中的array operators:
SELECT i.*
FROM
items i
JOIN items_colors ic ON ic.item_id = i.id
JOIN colors c ON c.id = ic.color_id
GROUP BY i.id
HAVING ARRAY_AGG(c.name) <@ ARRAY['green', 'blue'];
【讨论】:
感谢您的回答,我正在发现 PostgreSQL 中的数组运算符,它看起来很有趣!但是在这里我得到Query 1 OK
没有行。
@Etienne:请检查这个小提琴,SQL 工作正常,它可能在您的应用程序代码中。 dbfiddle.uk/…
是的,它在您的 dbfiddle 中运行良好。不知道为什么它不在我身边。我已经仔细检查过,我收到了这个错误(在 PostgreSql 12.5 上):sql Query 1 ERROR: ERROR: operator does not exist: character varying[] <@ text[] LINE 7: HAVING ARRAY_AGG(c.name) <@ ARRAY['green', 'blue']; ^ HINT: No operator matches the given name and argument types. You might need to add explicit type casts.
不管怎样,我现在有一个可行的解决方案,但我对那个很好奇。
@Etienne:两个项目必须是相同的数据类型,都是 VARCHAR 或都是 TEXT。我从不在我的数据库中使用 VARCHAR,只在 TEXT 中使用,并且从未遇到过这个问题。以上是关于MySQL 到 PostgreSQL - 在数组中查找并计算数组值的主要内容,如果未能解决你的问题,请参考以下文章
从 mysql 迁移到 postgresql 时,Laravel 雄辩的 ORM 不起作用