Вычисляемая колонка Hasura "Итого" - PullRequest
0 голосов
/ 19 марта 2020

Я хочу создать вычисляемый столбец в Hasura, который возвращает набор другой таблицы и включает в себя промежуточный итоговый столбец набора. Например:

table_a

id           product_id
-----------  ----------  
1            "1"      
2            "2"      
2            "3"      


table_b

id           product_id  qty   created_at
-----------  ----------  ---   ----------
1            "1"         6     01/01/20
2            "2"         4     01/02/20
3            "3"         2     01/02/20
4            "3"         2     01/02/20 
5            "1"         4     01/03/20
6            "2"         6     01/03/20

Желаемый ответ GQL:

{
  "data": {
    "table_a": [
      {
        "id": 1,
        "product_id": "1",
        "computed_table_b_rows": [
           {
              id: 1,
              product_id: "1",
              qty: 6,
              created_at: 01/01/20,
              running_total: 6,
           },
           {
              id: 5,
              product_id: "1",
              qty: 4,
              created_at: 01/03/20,
              running_total: 10,
           },
        ]
      }
    ]
  }
}

Вот то, что у меня пока что не работает:

CREATE FUNCTION filter_table_b(table_a_row table_a)
RETURNS SETOF table_b AS $$
  SELECT *,
  SUM (qty) OVER (PARTITION BY product_id ORDER BY created_at) as running_total
  FROM table_b
  WHERE product_id = table_a_row.product_id
$$ LANGUAGE sql STABLE;

1 Ответ

2 голосов
/ 20 марта 2020

Кажется, что SETOF должен быть подмножеством таблицы и не может иметь новых столбцов. Например, я попытался:

CREATE FUNCTION getfoo(int) RETURNS SETOF table_a AS $$
    SELECT *, 'asdf' as extra FROM table_a WHERE id = $1;
$$ LANGUAGE SQL;

, что привело к сообщенной Hasura ошибке:

SQL Execution Failed
postgres-error: return type mismatch in function declared to return table_a

{
    "path": "$.args[0].args",
    "error": "query execution failed",
    "internal": {
        "arguments": [],
        "error": {
            "status_code": "42P13",
            "exec_status": "FatalError",
            "message": "return type mismatch in function declared to return table_a",
            "description": "Final statement returns too many columns.",
            "hint": ""
        },
        "prepared": false,
        "statement": "CREATE FUNCTION getfoo(int) RETURNS SETOF table_a AS $$\n    SELECT *, 'asdf' as extra FROM table_a WHERE id = $1;\n$$ LANGUAGE SQL;"
    },
    "code": "postgres-error"
}

Однако есть несколько других вариантов:

  1. Добавить Столбец "промежуточного итога" на table_b сам (путем изменения определения функции. Подробно ниже.
  2. Если этого недостаточно, другой вариант - создать представление для table_b, в котором есть столбец running_total, используя sum и раздел. И затем создайте связь между table_a и table_b_view.
  3. Создайте триггер для table_b, чтобы при добавлении новой строки он вычислял столбец running_total и сохранял его, так как эти данные выглядят как stati c поскольку он основан на исторических данных.

Вариант 1 подробно описан ниже, поскольку он наиболее близко напоминает исходную реализацию (использование функции):

CREATE OR REPLACE FUNCTION public.table_b_running_total(table_b_row table_b)
 RETURNS bigint
 LANGUAGE sql
 STABLE
AS $function$
  SELECT SUM (qty)
  FROM table_b
  WHERE product_id = table_b_row.product_id
  AND created_at <= table_b_row.created_at
  LIMIT 1
$function$

enter image description here

С этим я смог получить желаемый результат - т. К. Требуемый ответ graphql точно не совпадает.

query:

query MyQuery {
  table_a(where:{ id: { _eq: 1 }}) {
    id
    product_id
    table_bs {
      id
      product_id
      qty
      created_at
      table_b_running_total
    }
  }
}

response :

{
  "data": {
    "table_a": [
      {
        "id": 1,
        "product_id": "1",
        "table_bs": [
          {
            "id": 1,
            "product_id": "1",
            "qty": 6,
            "created_at": "2020-01-01T00:00:00+00:00",
            "table_b_running_total": 6
          },
          {
            "id": 5,
            "product_id": "1",
            "qty": 4,
            "created_at": "2020-01-03T00:00:00+00:00",
            "table_b_running_total": 10
          }
        ]
      }
    ]
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...