【问题标题】:SQL JOIN: Select records by joining two tables by an array of ids usin IN or ANY()SQL JOIN:通过使用 IN 或 ANY() 通过 id 数组连接两个表来选择记录
【发布时间】:2022-02-15 03:36:27
【问题描述】:

是否可以使用第一个表中的 id 数组连接两个表?

示例

订单表

create table orders
(
  id UUID DEFAULT uuid_generate_v4(),
  user_id INT REFERENCES users (id),
  products_ids JSON NOT NULL,
  checkout_date TIMESTAMP DEFAULT NOW()
);

产品表

create table products
( 
  id SERIAL PRIMARY KEY, -- some other columns 
)
一些记录示例

订单表

id user_id products_ids checkout_date
0872ffb5-e347-447c-8b28-59368409cb84 1 [1,2] 1644863659550

产品表

id title other columns
1 'Lorem'
2 'Ipsum'

我想通过 products_ids 加入这两个表

SELECT * 
FROM orders AS o 
  INNER JOIN products AS p ON p.id = ANY(o.products_ids) 
WHERE o.usre_id = 1 
ORDER BY o.checkout_date

【问题讨论】:

  • 可能吗?当然。高效的?没有;它会像蜗牛一样快。
  • 你最好解决真正的问题,你的数据模型。
  • = any(...) 只能用于原生数组,不能用于 JSON 值。 1644863659550 也不是时间戳值
  • 对于模型,永远不要将数组存储在列中,而是使用单独的表。它可以是 (order_id, product_id)。
  • @ysth 这是一个未达到 1NF 的非规范化表。为了使查询实现高效,索引需要接受多条目。典型的 B-TREE 索引是行不通的。 PostgreSQL 实现了符合要求的 GIST 和 GIN 索引,但我认为 OP 不想处理实现它们的所有影响。

标签: sql postgresql


【解决方案1】:

正确的解决方案是正确规范化您的数据模型并创建常规的多对多关系表。


但是,如果您确实想深入研究并使用非规范化模型,则原生 int[] 数组比使用 JSON 列稍微好一些:

如果product_ids 定义为int[],那么您确实可以使用=any(...) 运算符:

select o.id, o.user_id, o.checkout_date, p.name
from orders o 
  join products p on p.id = any(o.product_ids);

Online example


如果你坚持使用 JSON,那么你可以使用 JSON/Path 查询来定义连接条件:

select o.id, o.user_id, o.checkout_date, p.name
from orders o 
  join products p on jsonb_path_exists(product_ids, '$[*] ? (@ == $id)', jsonb_build_object('id', p.id))

或者

select o.id, o.user_id, o.checkout_date, p.name
from orders o 
  join products p on o.product_ids @@ ('$[*] == '||p.id::text)::jsonpath
;

这假定product_ids 被定义为jsonb,而不是json 列。

Online example


但同样:正确的解决方案是使用正确规范化的数据模型。

【讨论】:

  • 谢谢,兄弟,我很感激。
  • 最后,我为多对多关系创建了一个新表,因为我想做的不是最佳实践。
  • @AbdelrhmanMohamed:不错的选择!
【解决方案2】:

在 mysql 中,您为此使用 JSON_TABLE:

select orders.id, products.title from orders
join json_table(orders.product_ids,"$[*]" COLUMNS(product_id int path "$")) order_products
join products on products.id=order_products.product_id

https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=2fe194aa6b192efe477efd365ec59bc0

https://stackoverflow.com/a/61732970/17389 可能会展示如何在 postgres 中执行此操作,但我对 postgres 的 json 支持了解不够,无法说明它的性能。

【讨论】:

  • 谢谢,兄弟,感谢您的宝贵时间。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-13
  • 2020-05-02
  • 1970-01-01
  • 2018-07-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多