【问题标题】:How to return different rows from the same table on single query as a list如何在单个查询中将同一表中的不同行作为列表返回
【发布时间】:2020-09-22 11:22:13
【问题描述】:

我有一个表,其中有一个布尔列,该列用于过滤一些响应。我需要将响应作为元组返回为{claimed, unclaimed}(假设该表称为winnings

在处理它时,我做了两个单独的查询以返回 claimed 然后 unclaimed 行并手动构建响应,然后我返回所有行而不检查布尔列并将其拆分到查询之外。现在我想知道是否有一种方法可以在同一个表上运行单个查询并将claimedunclaimed 作为单独的结果返回,主要是为了性能,希望它运行得更好。我试过用连接来做,但它返回一个包含两个项目元组的列表,比如:

[{claimed, unclaimed}, {claimed, unclaimed}]...

当我想要的时候:

{claimed, unclaimed}

# OR

[{claimed, unclaimed}]

最多,没有更多的元组。请注意,我没有运行原始查询,而是使用库,如果术语不正确,请原谅。

这是我运行的最后一个查询:

SELECT w0."claimed", w1."claimed"
FROM "winnings" AS w0
INNER JOIN "winnings" AS w1 ON TRUE
WHERE (w0."claimed" AND NOT (w1."claimed"))
LIMIT 10;

编辑:更多细节。

当我从上面运行查询时,得到的结果是:

=> SELECT w0."claimed", w1."claimed" FROM "winnings" AS w0 INNER JOIN "winnings" AS w1 ON TRUE WHERE (w0."claimed" AND NOT (w1."claimed")) LIMIT 10;

 claimed | claimed 
---------+---------
 t       | f
 t       | f
 t       | f
 t       | f
 t       | f
 t       | f
 t       | f
 t       | f
 t       | f
 t       | f
(10 rows)

这在我正在使用的语言 Elixir 上转换为以下内容:

[
  true: false,
  true: false,
  true: false,
  true: false,
  true: false,
  true: false,
  true: false,
  true: false,
  true: false,
  true: false
]

这是一个关键字列表,内部是一个元组列表,如[{true, false}, {true, false}] - 我想要:[{[true, true], [false, false]}]

意味着我想要 2 个列表,每个列表都有各自的行,仅在一个上声明,而在另一个上未声明。

我真的不介意它输出的类型,只要它包含两个列表以及我所说的行。

【问题讨论】:

  • 对不起,我不明白。查询返回一个表,即列和行。你能举个例子吗,比如说,有六行的获胜表,然后显示你期望从这些行得到的结果。
  • @ThorstenKettner 抱歉,我不够清楚。我刚刚发布了我期望的结果的更详细示例。
  • 所以这里主要讲的是如何在Elixir中选择某种格式的数据。因此,我已将您的请求标记为 elixir。希望知道该语言的人可以提供帮助。
  • 谢谢@ThorstenKettner - 我第一次没有把它放在适当的位置,因为我认为它与语言无关,因为我可以简单地在语言中的 SQL 上做同样的事情,或者我可以翻译任何 SQL 查询给我Elixir。
  • 无法理解您想要实现的目标。您执行的查询实际上与SELECT true, false FROM winnings 相同。请分享表格的 10 行以及您想要返回的确切输出。

标签: sql postgresql elixir


【解决方案1】:

要从行列表中获取第一列,可以使用Enum.map/2 获取每个元组的第一个元素:

Enum.map(rows, &elem(&1, 0))

如果你是 elixir 的新手,& 的语法可能会有点混乱。该代码是

的简写
Enum.map(rows, fn field -> elem(field, 0) end)

你可以把它变成一个函数,像这样对你的所有列执行此操作:

def columnize(rows = [first_row | _]) when is_tuple(first_row) do                 
  for column <- 1..tuple_size(first_row), do: Enum.map(rows, &elem(&1, column - 1))
end

def columnize([]) do
  []
end

hd/1 是一个用于获取列表中第一个元组的函数。 = [first_row | _] 部分保证参数是一个包含至少一个元素的列表; when is_tuple(first_row) 确保至少第一行是一个元组。

如果您想了解更多关于for 的信息,请联系comprehension

请注意,此函数假定所有行都具有相同的列数并且是元组(在查询结果中应该是这样;但在其他情况下可能不是),并且如果第一个将抛出 ArgumentError行比任何其他行都宽。如果列表的其他元素不是元组,也会导致错误。

虽然这感觉很单调。这可能是 XY 问题吗?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-11-14
    • 1970-01-01
    • 1970-01-01
    • 2021-03-03
    • 2015-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多