BigQuery - Свернуть ряды по группам - PullRequest
0 голосов
/ 03 февраля 2020

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

enter image description here

Со следующими значениями:

enter image description here

И я ожидаю, чтобы результат был следующим:

---------------------------------------
| Row | col_1 | col_2 | col_3 | col_4 |
---------------------------------------
|  1  |   4   | NULL  | NULL  |  NULL |
---------------------------------------
|  2  |   0   |   1   |  2    |  NULL |
---------------------------------------
|  3  |   5   |  NULL |  6    |   7   |
---------------------------------------

В приведенном выше примере видно, что строки 2 и 3 свернуты, поскольку оба имеют значение 1 для col_2. Точно так же строки 4 и 5 свернуты, потому что у них обоих есть 6 в col_3. Я попробовал следующее, но не смог заставить его работать. У кого-нибудь есть предложения?

SELECT
  FIRST_VALUE(c1.col_1) OVER (PARTITION BY c1.col_1 ORDER BY 1 ASC ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS col_1,
  FIRST_VALUE(c2.col_2 IGNORE NULLS) OVER (PARTITION BY c1.col_1 ORDER BY 1 ASC ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS col_2,
  FIRST_VALUE(c3.col_3 IGNORE NULLS) OVER (PARTITION BY c2.col_2 ORDER BY 1 ASC ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS col_3,
  FIRST_VALUE(c4.col_4 IGNORE NULLS) OVER (PARTITION BY c3.col_3 ORDER BY 1 ASC ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS col_4,
FROM
  dataset.collapse_test  c1
LEFT JOIN
  dataset.collapse_test c2
ON
  c1.col_2 = c2.col_2
LEFT JOIN
  dataset.collapse_test c3
ON
  c2.col_2 = c3.col_2
LEFT JOIN
  dataset.collapse_test c4
ON
  c3.col_3 = c4.col_3

1 Ответ

0 голосов
/ 03 февраля 2020

Есть некоторые проблемы с этим запросом, так как, как сказал @Gordon Linoff в комментарии, некоторые строки могут быть проблемными c, когда более одного значения совпадают.

Поэтому здесь я помещаю свою попытку, которая генерирует нужные вам значения, но также сохраняет старые, поскольку в некоторых случаях трудно понять, когда их хранить, как было сказано ранее.

Все, мы создаем таблицу:

CREATE TABLE `dataset.collapse` (
   col_1 INT64,
   col_2 INT64,
   col_3 INT64,
   col_4 INT64,
) as SELECT 4 as col_1, null as col_2, null as col_3, null as col_4 UNION ALL
     SELECT 0 as col_1, 1 as col_2, null as col_3, null as col_4 UNION ALL
     SELECT null as col_1, 1 as col_2, 2 as col_3, null as col_4 UNION ALL
     SELECT null as col_1, null as col_2, 6 as col_3, 7 as col_4 UNION ALL
     SELECT 5 as col_1, null as col_2, 6 as col_3, null as col_4

И затем мы запускаем наше решение для этого случая, я использовал функцию IFNULL, чтобы сохранить только ненулевые значения и INNER JOIN в качестве условия равных значений :

SELECT
   IF
    (t1.col_1 IS NULL,
      CAST(CONCAT(IFNULL(t1.col_1,
          t2.col_1)) AS INT64),
    t1.col_1) AS c1,
   IF
    (t1.col_2 IS NULL,
     CAST(CONCAT(IFNULL(t1.col_2,
         t2.col_2)) AS INT64),
    t1.col_2) AS c2,
   IF
    (t1.col_3 IS NULL,
     CAST(CONCAT(IFNULL(t1.col_3,
          t2.col_3)) AS INT64),
    t1.col_3) AS c3,
   IF
    (t1.col_4 IS NULL,
     CAST(CONCAT(IFNULL(t1.col_4,
          t2.col_4)) AS INT64),
     t1.col_4) AS c4
FROM
  `project.dataset.collapse` AS t1
INNER JOIN
  `project.dataset.collapse` AS t2
ON
  t1.col_2 = t2.col_2
  OR t1.col_1 = t2.col_1
  OR t1.col_3 = t2.col_3
  OR t1.col_4 = t2.col_4
GROUP BY
  c1,
  c2,
  c3,
  c4

И решение, которое мы получаем, это:

enter image description here

Чтобы удалить старые значения, решение будет быть примерно таким:

SELECT
   *
FROM (previous_query)
   WHERE
     CONCAT(IFNULL(c1,
           -1),IFNULL(c2,
           -1),IFNULL(c3,
           -1),IFNULL(c4,
           -1)) 
     NOT IN (
        SELECT
            CONCAT(IFNULL(col_1,
             -1),IFNULL(col_2,
             -1),IFNULL(col_3,
             -1),IFNULL(col_4,
             -1))
        FROM
           `project.dataset.collapse`
        WHERE
           CONCAT(IFNULL(col_1,
              -1),IFNULL(col_2,
              -1),IFNULL(col_3,
              -1),IFNULL(col_4,
              -1)) = CONCAT(IFNULL(c1,
                    -1),IFNULL(c2,
                    -1),IFNULL(c3,
                    -1),IFNULL(c4,
                    -1)) ))

Имейте в виду, что это решение также удалит [4 null null null] строку.

Результат:

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...