Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Postgresql 在Elixir with Postgres中,如何让数据库返回未使用的枚举值?_Postgresql_Enums_Elixir_Ecto_Processing Efficiency - Fatal编程技术网

Postgresql 在Elixir with Postgres中,如何让数据库返回未使用的枚举值?

Postgresql 在Elixir with Postgres中,如何让数据库返回未使用的枚举值?,postgresql,enums,elixir,ecto,processing-efficiency,Postgresql,Enums,Elixir,Ecto,Processing Efficiency,我有一个外种名。博士后: # @see: https://en.wikipedia.org/wiki/ISO_4217 defmodule PricingEngine.Pricing.CurrencyEnum do @options [ :AED, :AFN, # snip... :ZWL ] use EctoEnum.Postgres, type: :currency, enums: @options def values, d

我有一个外种名。博士后:

# @see: https://en.wikipedia.org/wiki/ISO_4217
defmodule PricingEngine.Pricing.CurrencyEnum do
  @options [
    :AED,
    :AFN,
    # snip...
    :ZWL
  ]
  use EctoEnum.Postgres,
    type: :currency,
    enums: @options

  def values, do: @options
end
此枚举已包含在我们的Postgres数据库中

我们还有一个结构:

defmodule PricingEngine.Pricing.Currency do
  use Ecto.Schema
  import Ecto.Changeset

  schema "currencies" do
    field(:currency, PricingEngine.Pricing.CurrencyEnum)

    timestamps()
  end

  @doc false
  def changeset(currency, attrs) do
    currency
    |> cast(attrs, [:currency])
    |> validate_required([:currency])
    |> unique_constraint(:currency)
  end
end
我们目前可以成功地使用以下功能来确定哪些货币处于活动/使用状态:

  def active_currency_isos do
    Repo.all(select(Currency, [record], record.currency))
  end

  defdelegate all_currency_isos,
    to: CurrencyEnum,
    as: :values

  def inactive_currency_iso do
    Pricing.all_currency_isos() -- Pricing.active_currency_isos()
  end
这是可行的,但我相信如果我们只是向数据库询问这些信息,这可能会更有效率


你知道怎么做吗?

如果你想得到所有使用过的枚举的列表,你只需要在货币字段上做一个区分。这将使用Postgres DISTINCT ON运算符:

from(c in Currency,
 distinct: c.currency,
 select: c.currency
)
这将查询表(按货币列唯一),并仅返回货币列值。您应该获得表中存在的所有枚举的数组

这样做有一些效率问题,可以通过物化视图、查找表、内存缓存等来缓解。但是,如果您的数据集不是非常大,您应该可以使用它一段时间

编辑: 根据响应,我将展示如何获取未使用的枚举

有两种方法可以做到这一点

纯SQL 此查询将获取所有已使用的枚举,并与整个可用枚举集有所不同。我们用于执行此操作的运算符是EXCEPT,您可以获得具有enum_范围的所有可用枚举的列表。我将使用unnest将枚举类型数组转换为单独的行:

选择unnestenum_rangeNULL::currency作为未使用的_枚举 除了 在c.name上选择DISTINCT c.name 从货币c 通过执行以下操作,可以在EXTO中执行此原始SQL:

Ecto.Adapters.SQL.query!(MyApp.Repo, "SELECT unnest(...", [])
从中您将得到一个Postgresx。结果是您必须从中获取值:

result
|> Map.get(:rows, [])
|> List.flatten()
|> Enum.map(&String.to_existing_atom/1)
我真的不确定有什么方法可以用纯EXTO来编写这个查询,但是如果你明白了,请告诉我

编码 您可以使用distinct执行我之前发布的第一个查询,然后在代码中执行差异

query = from(c in Currency,
  distinct: c.currency,
  select: c.currency
)

CurrencyEnum.__enums__() -- Repo.all(query)

就性能而言,任何一种方法都可能可以忽略不计,因此这取决于您。

是否应在调用中使用distinct:true选项进行选择?另外,我也不知道如何查询数据库中缺少的信息。我对distinct:true一无所知,因此我无法评论是否需要使用它。数据库包含一组完整的枚举。它还包含一个表,可以使用这些值,也可以不使用这些值。这样做的目的是获取表中使用的值,然后只返回那些未包含在表中收集的值中的枚举。为响应干杯!对不起,我的问题有点模棱两可。实际上,我希望数据库返回未使用的枚举,即非活动值