PostgreSQL - 使用json函数查询时返回单行

时间:2016-04-11 23:08:14

标签: postgresql

我们将状态转换数据存储在json列中,如下所示:

state: {
  current_state: 'state_three',
  transitions: [
    { from: 'state_two', to: 'state_three', at: [time in iso8601] },
    { from: 'state_one', to: 'state_two', at: [time in iso8601] }
  ]
}

有时我们需要在一段时间之前查询处于某种状态的行,因此我们有一个如下所示的查询:

SELECT *
  FROM my_table, json_array_elements("my_table"."state"->'transitions') as state_changes
  WHERE ((state_changes->>'to' = 'state_two')
    AND (state_changes->>'at' < '2016-04-11 00:00:00.000000'))

此查询的问题在于,在某些情况下,我们可能会多次转换到相关状态(state_two):

state: {
  current_state: 'state_two',
  transitions: [
    { from: 'state_two', to: 'state_one', at: [time in iso8601] },
    { from: 'state_one', to: 'state_two', at: [time in iso8601] },
    { from: 'state_two', to: 'state_one', at: [time in iso8601] },
    { from: 'state_one', to: 'state_two', at: [time in iso8601] }
  ]
}

在这种情况下,当WHERE子句与多个transitions数组元素匹配时,查询将多次返回同一行。是否有另一种方法来构造此查询,以便所有匹配的行只返回一次?

1 个答案:

答案 0 :(得分:0)

像(未经测试)的东西:

SELECT *
  FROM my_table
  WHERE EXISTS (
    SELECT 1 
    FROM json_array_elements(state->'transitions') state_changes(v)
    WHERE (
      (v->>'to' = 'state_two') AND 
      (v->>'at' < '2016-04-11 00:00:00.000000'))
  )

提示:如果要在SQL查询中使用其元素,请不要使用JSON数据类型。改为使用表格/列。