PostgreSQL Ecto - array_agg(json_build_object 中的 DISTINCT
PostgreSQL Ecto - DISTINCT inside array_agg(json_build_object
我正在尝试使用 array_agg
将数组合并到单个记录中。
这是我现在尝试使用 Ecto PostgreSQL 实现的mysql:
SELECT p.p_id, p.`p_name`, p.brand, GROUP_CONCAT(DISTINCT CONCAT(c.c_id,':',c.c_name) SEPARATOR ', ') as categories, GROUP_CONCAT(DISTINCT CONCAT(s.s_id,':',s.s_name) SEPARATOR ', ') as shops
在 PostgreSQL 中,GROUP_CONCAT
变为 array_agg
这是可行的,但我需要让它只显示不同的类别和商店。我需要添加 json_build_object
才能显示更多类别和商店的 id 字段。:
def create_query(nil, categories, shop_ids) do
products_shops_categories = from p in Product,
join: ps in ProductShop, on: p.id == ps.p_id,
join: s in Shop, on: s.id == ps.s_id,
join: pc in ProductCategory, on: p.id == pc.p_id,
join: c in Subcategory, on: c.id == pc.c_id,
where: c.id in ^categories,
where: s.id in ^shop_ids,
group_by: [p.id, s.id],
select: %{product: p, categories: fragment("array_agg(json_build_object('id', ?, 'name', ?))", c.id, c.name), shops: fragment("array_agg( json_build_object('id', ?, 'name', ?, 'point', ?))", s.id, s.name, s.point)}
end
当我将 DISTINCT
添加到 array_agg
时,它会导致:
** (Postgrex.Error) ERROR 42809 (wrong_object_type): DISTINCT specified, but json_build_object is not an ag
gregate function
最终解决方案感谢Pozs的建议:
def create_query(nil, categories, shop_ids) do
products_shops_categories = from p in Product,
distinct: p.id,
join: ps in ProductShop, on: p.id == ps.p_id,
join: s in Shop, on: s.id == ps.s_id,
join: pc in ProductCategory, on: p.id == pc.p_id,
join: c in Subcategory, on: c.id == pc.c_id,
where: c.id in ^categories,
where: s.id in ^shop_ids,
group_by: [p.id, p.name, p.brand],
select: %{product: p, categories: fragment("json_agg( DISTINCT (?, ?)) AS category", c.id, c.name), shops: fragment("json_agg( DISTINCT (?, ?, ?)) AS shop", s.id, s.name, s.point)}
end
关于下面a_horse_with_a_name的解决方案:
我只尝试了类别:
group_by: [p.id, p.name, p.brand],
select: %{product: p, categories: fragment("string_agg(DISTINCT CONCAT(?,':',?), ', ') AS categories", c.id, c.name), shops: fragment("json_agg( DISTINCT (?, ?, ?)) AS shop", s.id, s.name, s.point)}
而且它也有效。只取决于您希望数组采用哪种格式。sting_agg
是逗号分隔的字符串。
使用string_agg()
代替group_concat()
:
SELECT p.p_id,
p.p_name,
p.brand,
string_agg(DISTINCT CONCAT(c.c_id,':',c.c_name), ', ') as categories,
string_agg(DISTINCT CONCAT(s.s_id,':',s.s_name), ', ') as shops
FROM ..
我正在尝试使用 array_agg
将数组合并到单个记录中。
这是我现在尝试使用 Ecto PostgreSQL 实现的mysql:
SELECT p.p_id, p.`p_name`, p.brand, GROUP_CONCAT(DISTINCT CONCAT(c.c_id,':',c.c_name) SEPARATOR ', ') as categories, GROUP_CONCAT(DISTINCT CONCAT(s.s_id,':',s.s_name) SEPARATOR ', ') as shops
在 PostgreSQL 中,GROUP_CONCAT
变为 array_agg
这是可行的,但我需要让它只显示不同的类别和商店。我需要添加 json_build_object
才能显示更多类别和商店的 id 字段。:
def create_query(nil, categories, shop_ids) do
products_shops_categories = from p in Product,
join: ps in ProductShop, on: p.id == ps.p_id,
join: s in Shop, on: s.id == ps.s_id,
join: pc in ProductCategory, on: p.id == pc.p_id,
join: c in Subcategory, on: c.id == pc.c_id,
where: c.id in ^categories,
where: s.id in ^shop_ids,
group_by: [p.id, s.id],
select: %{product: p, categories: fragment("array_agg(json_build_object('id', ?, 'name', ?))", c.id, c.name), shops: fragment("array_agg( json_build_object('id', ?, 'name', ?, 'point', ?))", s.id, s.name, s.point)}
end
当我将 DISTINCT
添加到 array_agg
时,它会导致:
** (Postgrex.Error) ERROR 42809 (wrong_object_type): DISTINCT specified, but json_build_object is not an ag
gregate function
最终解决方案感谢Pozs的建议:
def create_query(nil, categories, shop_ids) do
products_shops_categories = from p in Product,
distinct: p.id,
join: ps in ProductShop, on: p.id == ps.p_id,
join: s in Shop, on: s.id == ps.s_id,
join: pc in ProductCategory, on: p.id == pc.p_id,
join: c in Subcategory, on: c.id == pc.c_id,
where: c.id in ^categories,
where: s.id in ^shop_ids,
group_by: [p.id, p.name, p.brand],
select: %{product: p, categories: fragment("json_agg( DISTINCT (?, ?)) AS category", c.id, c.name), shops: fragment("json_agg( DISTINCT (?, ?, ?)) AS shop", s.id, s.name, s.point)}
end
关于下面a_horse_with_a_name的解决方案:
我只尝试了类别:
group_by: [p.id, p.name, p.brand],
select: %{product: p, categories: fragment("string_agg(DISTINCT CONCAT(?,':',?), ', ') AS categories", c.id, c.name), shops: fragment("json_agg( DISTINCT (?, ?, ?)) AS shop", s.id, s.name, s.point)}
而且它也有效。只取决于您希望数组采用哪种格式。sting_agg
是逗号分隔的字符串。
使用string_agg()
代替group_concat()
:
SELECT p.p_id,
p.p_name,
p.brand,
string_agg(DISTINCT CONCAT(c.c_id,':',c.c_name), ', ') as categories,
string_agg(DISTINCT CONCAT(s.s_id,':',s.s_name), ', ') as shops
FROM ..