Как разделить записи одного и того же ключа в определенном диапазоне и посчитать количество этих разделов в sql? - PullRequest
0 голосов
/ 03 июня 2019

Chrome History База данных SQlite 3 имеет таблицу urls, например:

CREATE TABLE "urls"(
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  url LONGVARCHAR,
  title LONGVARCHAR,
  visit_count INTEGER DEFAULT 0 NOT NULL,
  typed_count INTEGER DEFAULT 0 NOT NULL,
  last_visit_time INTEGER NOT NULL,
  hidden INTEGER DEFAULT 0 NOT NULL
  )

Если вы также используете Chrome и OS X, вы можете найти ее по адресу ~/Library/Application Support/Google/Chrome/Default/History.Другие системы могут видеть этот пост: Где Chrome сохраняет свою базу данных SQLite в?

Я хочу сосчитать числа title, но в отдельном промежутке времени (как день).

Упрощенная таблица выглядит следующим образом:

  id    | title |  last_visit_time  |
--------+-------+-------------------+
"240255"  "foo"  "13197393082183934"
"240256"  "foo"  "13197393082183934"
"240259"  "foo"  "13197393103031880"
"251615"  "foo"  "13201270874907168"
"251616"  "foo"  "13201270904026269"
"251631"  "foo"  "13201271376777156"
"258228"  "goo"  "13203150937196411"
"258229"  "goo‬"  "13203150937196411"
"258230"  "goo‬"  "13203150937196411"

last_visit_time «отформатирован как число микросекунд с января 1601 года».Для данного span (например, 86400000000, день в микросекундах) все одинаковые title учитываются только 1 раз, потому что они находятся в одном и том же периоде.

Часть псевдокода, которая должна учитываться для отдельного title в стиле Python выглядит так:

count = 0
all_last_visit_time_sorted = all_last_visit_time.sort() # generally it should be sorted because the `history` data was added into database in time order.
span = 86400000000 # a day in microseconds
current_base_time = all_last_visit_time_sorted[0]
for last_visit_time in all_last_visit_time_sorted:
    if last_visit_time - current_base_time > span:
          count += 1
          current_base_time = last_visit_time

Чтобы быть более понятным, раздел выглядит так:

  id    | title |  last_visit_time  |
--------+-------+-------------------+
"240255"  "foo"  "13197393082183934"
"240256"  "foo"  "13197393082183934"
"240259"  "foo"  "13197393103031880"
------------------------------------
"251615"  "foo"  "13201270874907168"
"251616"  "foo"  "13201270904026269"
"251631"  "foo"  "13201271376777156"
------------------------------------
"258228"  "goo"  "13203150937196411"
"258229"  "goo‬"  "13203150937196411"
"258230"  "goo‬"  "13203150937196411"

Тогда я ожидаю:

 title |  count |
-------+--------+
 "foo" |    2   |
 "goo" |    1   |

Я не знаю, как это сделать с SQL, хотя после Google такие ключевые слова, как window function, subquery и т. Д.

ps: пример данных

INSERT INTO urls VALUES ("460534","https://stackoverflow.com/questions/ask","Ask a Question - Stack Overflow","1","0","13197393082183934","0");
INSERT INTO urls VALUES ("460535","https://stackoverflow.com/questions/ask/wizard","Ask a Question - Stack Overflow","1","0","13197393082183965","0");
INSERT INTO urls VALUES ("460536","https://stackoverflow.com/questions/ask?guided=true","Ask a Question - Stack Overflow","1","0","13197393082184036","0");
INSERT INTO urls VALUES ("460537","https://stackoverflow.com/search?q=%5Bhadoop%5D","Highest Voted 'hadoop' Questions - Stack Overflow","1","0","13196783835451652","0");
INSERT INTO urls VALUES ("460538","https://stackoverflow.com/questions/tagged/hadoop","Highest Voted 'hadoop' Questions - Stack Overflow","1","0","13196783835452653","0");
INSERT INTO urls VALUES ("460539","https://stackoverflow.com/questions/ask","Ask a Question - Stack Overflow","1","0","13407393082183934","0");
INSERT INTO urls VALUES ("460540","https://stackoverflow.com/questions/ask/wizard","Ask a Question - Stack Overflow","1","0","13407393082184035","0");
INSERT INTO urls VALUES ("460541","https://stackoverflow.com/questions/ask?guided=true","Ask a Question - Stack Overflow","1","0","13407393082184236","0");

1 Ответ

1 голос
/ 03 июня 2019

Для меня это просто еще одна разновидность Пробелов и островов .Вы должны сравнить last_visit_time каждой строки с предыдущей строкой.Если они находятся в пределах одного дня друг от друга (86400000000), то вы хотите считать их как 1 посещение.Мы выведем столбец, чтобы указать, находится ли текущая строка в течение 1 дня от предыдущей строки.

Далее вам нужно взять этот новый производный столбец (gap в dbfiddle) и выполнитьсумма на это.Каждый раз, когда разрыв становится равным 1, вы видите, что текущая сумма увеличивается.Таким образом, все строки, в которых итоговая сумма одинакова, вы будете считать их вместе.

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

Вот DBFiddle (с несколькими дополнительными строками, добавленными к вашему первому набору образцов данных, чтобы получить еще пару дней), разбитых шаг за шагом.

Вот последний(безобразный) запрос:

with fst as (
select
id, title,
last_Visit_time,
lag(last_visit_time,1,last_visit_time) over (partition by title order by last_visit_time) ,
case 
when last_visit_time - lag(last_visit_time,1,last_visit_time) over (partition by title order by last_visit_time)  < 86400000000 
then 0
else 1
end as gap

from
<your table>
order by last_visit_time)


select
 title,
 count (distinct grouper)
 from (
select
id,
title,
gap,
sum(gap) over (partition by title order by last_visit_time rows unbounded preceding) as grouper
from 
fst) t
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...