PostgreSQL Ecto - array_agg中的DISTINCT(json_build_object

时间:2017-05-31 06:52:26

标签: postgresql elixir ecto elixir-framework

我尝试使用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

这是有效的,但我需要让它只显示DISTINCT类别和商店。我需要添加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是逗号分隔的字符串。

1 个答案:

答案 0 :(得分:1)

使用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 ..