Наиболее эффективный запрос для извлечения временной шкалы хэштегов, сгруппированных по дате в BigQuery - PullRequest
0 голосов
/ 11 февраля 2019

Я хочу извлечь временную шкалу хэштега, сгруппированную по дате, из столбца данных заметок.Данные - это столбец JSON.Мы должны посчитать хэштеги, которые могут быть в свойстве 't' ИЛИ ​​'d'

Table: notes
----------------------------------------------------------------------
| id | data                                    | created_at          |
----------------------------------------------------------------------
| 1  | {"t":"#hash1 title","d":"#hash1 desc"}  | 2018-01-01 10:00:00 |
| 2  | {"t":"#hash1 title","d":"#hash1 desc"}  | 2018-01-01 11:00:00 |
| 3  | {"t":"title","d":"#hash1 #hash2 desc"}  | 2018-01-03 10:00:00 |

Как описано ниже, для требуемого вывода необходим каждый хэштег с соответствующим временным графиком в формате: DATE:COUNT|DATE:COUNT|DATE:COUNT

Required Output
----------------------------------------------------------
| hashtag                    | timeline                  |
----------------------------------------------------------
| #hash1                     | 2018-01-01:4|2018-01-03:1 |
| #hash2                     | 2018-01-03:1              |

Какой наиболее эффективный одиночный запрос обладает всеми этими функциями:

  • Извлечение хештегов из свойства 't' и 'd' данных.
  • Подсчет числаХэштеги, сгруппированные по дате.
  • Объединение соответствующей временной шкалы хэштега в нужном формате.

ОБНОВЛЕНИЕ 1: Ниже приведен мой запрос.Это неэффективно, потому что я должен UNNEST 2 раза.Я не могу понять, как сделать это эффективным.

WITH
r0 AS (
  SELECT JSON_EXTRACT_SCALAR(data, '$[d]') as data, created_at
  FROM `notes`
  UNION ALL
  SELECT JSON_EXTRACT_SCALAR(data, '$[t]') as data, created_at
  from `notes`      
),
r1 AS (
  SELECT created_at, REGEXP_EXTRACT_ALL(data, r"#(\w*[0-9a-zA-Z]+\w*[0-9a-zA-Z])") AS hashtags
  FROM r0
),
r2 AS (
  SELECT ARRAY_AGG(DATE(created_at)) as created_at_dates, hashtag
  FROM r1, UNNEST(hashtags) hashtag
  GROUP BY hashtag
),
r3 AS (
  SELECT created_at_date, hashtag
  FROM r2, UNNEST(created_at_dates) created_at_date
),
r4 AS (
  SELECT hashtag, created_at_date, count(created_at_date) as day_val
  FROM r3
  GROUP BY hashtag, created_at_date
  ORDER BY created_at_date
)
SELECT hashtag, STRING_AGG(CONCAT(CAST(created_at_date as STRING),':',CAST(day_val as STRING)), '|') as timeline
FROM r4
GROUP BY hashtag

Ответы [ 2 ]

0 голосов
/ 11 февраля 2019

Ниже для стандартного SQL BigQuery

#standardSQL
SELECT hashtag,
  STRING_AGG(CONCAT(day, ':', cnt), '|' ORDER BY day) AS timeline
FROM (
  SELECT hashtag,
    CAST(DATE(created_at) AS STRING) day,
    CAST(COUNT(1) AS STRING) cnt
  FROM `project.dataset.table`,
  UNNEST(REGEXP_EXTRACT_ALL(data, r'"(?:t|d)":(".*?")')) val,
  UNNEST(REGEXP_EXTRACT_ALL(val, r'(#.*?)\s')) hashtag
  GROUP BY hashtag, day
)
GROUP BY hashtag

Если вам нужно извлечь больше, чем просто свойства t и d - вы просто добавляете их в список (?:t|d) вместо использования несколькихUNION ALL

, если выполнить выше для данных примера в вашем вопросе - результат

Row hashtag timeline     
1   #hash1  2018-01-01:4|2018-01-03:1    
2   #hash2  2018-01-03:1      

Обновление по адресу "глубокая структура", упомянутое в комментарии @ user2576951

См. Ниже обновление вместе с фиктивными данными для проверки с

#standardSQL
WITH `project.dataset.table` AS (
  SELECT 1 id, '{"x":"title","t":"#hash1 title","d":"help #hash1 desc"}' data, TIMESTAMP '2018-01-01 10:00:00' created_at UNION ALL
  SELECT 2, '{"t":"#hash1 title","y":"title","d":"#hash1 desc"}', '2018-01-01 11:00:00' UNION ALL
  SELECT 3, '{"t":"title","d":"#hash1 #hash2 desc","z":"title"}', '2018-01-03 10:00:00' UNION ALL
  SELECT 4, '{"t":"title","d":"description","snippet":{"t":"#hash1","st":"#hash1", "ssd":"#hash3"}}', '2018-02-03 10:00:00'
)
SELECT hashtag,
  STRING_AGG(CONCAT(day, ':', cnt), '|' ORDER BY day) AS timeline
FROM (
  SELECT 
    hashtag, 
    CAST(DATE(created_at) AS STRING) day,
    CAST(COUNT(1) AS STRING) cnt
  FROM `project.dataset.table`,
  UNNEST(REGEXP_EXTRACT_ALL(data, r'"(?:t|d|st|sd)":"(.*?)"')) val,
  UNNEST(REGEXP_EXTRACT_ALL(val, r'(#.*?)(?:$|\s)')) hashtag
  GROUP BY hashtag, day
)
GROUP BY hashtag
-- ORDER BY hashtag    

с выводом

Row hashtag timeline     
1   #hash1  2018-01-01:4|2018-01-03:1|2018-02-03:2   
2   #hash2  2018-01-03:1       

, как вы можете видеть здесь, хэштеги собраны из вложенных элементов и "ssd "не было найдено, хотя sd является его частью

Я думаю, что выше рассматриваются ваши комментарии / проблемы

0 голосов
/ 11 февраля 2019

Я не уверен, что это «самый эффективный», но это должно делать то, что вы хотите:

select hashtag,
       array_agg(concat(created_at, ':', cast(cnt as string))
from (select hashtag, created_at, count(*) as cnt
      from ((select json_extract_scalar(data, '$[d]') as hashtag, created_at
             from t
            ) union all
            (select json_extract_scalar(data, '$[t]') as hashtag, created_at
             from t
            ) 
           ) h
      group by hash
     ) ch
group by hashtag;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...