php - 多对多关系、IN 运算符和不正确结果的可能性

标签 php postgresql optimization many-to-many

我在创建最佳 SQL 查询时遇到了问题。我有私有(private)消息系统,用户可以在其中向许多用户或用户组发送一条消息。收件人存储在单个文本列中(不要问我为什么我不负责设计它),就像这样:

[60,63,103,68]

另外,我添加了新的文本列,其中放置了用户所属的组,因此我可以将其作为数据库中的组:

[55,11,11,0]

现在我想获取所有用户(接收者)及其组。我有一个表,其中包含用户和组 ID 之间的关系。问题是单个用户可以属于多个组,例如用户 60 可以在组 ID 55 和 11 中。我想以最佳方式进行(列中可以存储 50 多个接收者......)所以我可以这样写查询:

SELECT u.name, u.last_name, g.group_name

                    FROM 
                        user u
                    LEFT JOIN
group g ON u.id = g.user_id
                    WHERE
                        u.id IN (".$users.") and
g.id IN (".$groups.")

不幸的是,查询返回的组名可能不正确 - 与我放置在 WHERE 中的组 ID 相关联。我可以创建 PHP foreach 并使用我拥有的 ID 获取用户和他的组:

foreach($user as $key => $single)
{
$sql = "...
      where u.id = $single AND g.id = $group[$key] ";
}

但我认为这是非常糟糕的方式。有没有办法在单个查询中获取用户和指定组?

最佳答案

由于用户和组仅通过他们在列表中的顺序位置链接,因此您需要利用它。

快速而肮脏的方法是 unnest()并行:

SELECT u.name, u.last_name, g.group_name
FROM  (   
   SELECT unnest(string_to_array('3,1,2', ',')::int[])    AS usr_id  -- users
        , unnest(string_to_array('10,11,12', ',')::int[]) AS grp_id  -- groups
  ) sel
JOIN   usr_grp ug USING (usr_id, grp_id)
JOIN   usr u USING (usr_id)
JOIN   grp g USING (grp_id);

注意我是如何替换 SQL key words 的像 usergroup 作为标识符。

-> SQLfiddle

这样,数组中具有相同序号位置的元素(从逗号分隔列表转换而来)形成一行。两个数组都需要具有相同数量的元素,否则操作将生成笛卡尔积。根据你的描述,这里应该是这样的。添加代码以验证是否可能违反该条件。

更清洁的替代品

虽然上面的工作可靠,但它是 SRF(设置返回函数)的非标准 Postgres 特性,有些人不赞成。

有更简洁的方法可以做到这一点。即将发布的 9.4 版 Postgres 将发布一个新功能:WITH ORDINALITY,允许更简洁的代码。这个相关的答案证明了两者:
PostgreSQL unnest() with element number

关于php - 多对多关系、IN 运算符和不正确结果的可能性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21782374/

相关文章:

javascript - 在 javascript 中处理 PHP 脚本

php - 如何添加嵌套 xml 元素

php - 如何检查我是否创建了最佳的mysql数据库?

linux - 无法在终端代码中为带连字符 (-) 的用户名添加密码

postgresql - OSGi + JPA(postgresql)

objective-c - 算法代码优化 : Find the Equilibirum: Find an index in an array such that its prefix sum equals its suffix sum

php - 如何在 PHP 中使用 BRT 时区缩写解析字符串

mysql - 对于 SELECT * WHERE id ='1blah' 这样的查询,PostgreSQL 和 Oracle 会如何表现?

python - 加快 ~50GB CSV 文件的轻处理

sql - 为什么创建不相关的索引会使我的查询更快?