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[] &lt;@ text[] LINE 7: HAVING ARRAY_AGG(c.name) &lt;@ 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 - 在数组中查找并计算数组值的主要内容,如果未能解决你的问题,请参考以下文章

PostgreSQL - 返回数组

将 MySql 转换为 PostgreSQL

从 mysql 迁移到 postgresql 时,Laravel 雄辩的 ORM 不起作用

在 Linux (Kubuntu) 上从 MySQL 迁移到 PostgreSQL

Postgresql 10 jsonb 到多行表

PostgreSQL 与 MySQL 有何不同? [关闭]