2015-09-14 16 views
11

Wprowadzenie
w moim projekcie zapisuję strony z Facebooka i ich podobną liczbę, a także podobną liczbę dla każdego kraju. Mam tabelę dla stron Facebook, jedną dla języków, jedną dla korelacji między stroną na Facebooku i językiem (i licząc podobieństwa) i jedną tabelą, która zapisuje te dane jako historię. Chcę uzyskać stronę o największym wzroście liczby polubień w określonym przedziale czasu.Analiza regresyjna w MySQL

danych do pracy z

mam stripping niepodlegania istotnych informacji z zapytaniami tworzą.

tabelę zawierającą strony facebook

CREATE TABLE `pages` (
    `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    `facebook_id` varchar(255) COLLATE utf8_unicode_ci NOT NULL, 
    `facebook_name` varchar(255) COLLATE utf8_unicode_ci NOT NULL, 
    `facebook_likes` int(11) NOT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 

Przykład Dane:

INSERT INTO `facebook_pages` (`id`, `facebook_id`, `facebook_name`, `facebook_likes`) 
VALUES 
    (1, '552825254796051', 'Mesut Özil', 28593755), 
    (2, '134904013188254', 'Borussia Dortmund', 13213354), 
    (3, '310111039010406', 'Marco Reus', 12799627); 

tabelę zawierającą języki

CREATE TABLE `languages` (
    `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    `language` varchar(5) COLLATE utf8_unicode_ci NOT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 

Przykładowe dane

INSERT INTO `languages` (`id`, `language`) 
VALUES 
    (1, 'ID'), 
    (2, 'TR'), 
    (3, 'BR'); 

tabelę zawierającą związek

CREATE TABLE `language_page_likes` (
    `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    `language_id` int(10) unsigned NOT NULL, 
    `facebook_page_id` int(10) unsigned NOT NULL, 
    `likes` int(11) DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    // Foreign key stuff 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 

Przykładowe dane

INSERT INTO `language_page_likes` (`id`, `language_id`, `facebook_page_id`) 
VALUES 
    (1, 1, 1), 
    (2, 2, 1), 
    (3, 3, 1), 
    (47, 3, 2), 
    (51, 1, 2), 
    (53, 2, 2), 
    (92, 3, 3), 
    (95, 2, 3), 
    (97, 1, 3); 

tabeli zawierającej historię

CREATE TABLE `language_page_likes_history` (
    `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    `language_page_likes_id` int(10) unsigned NOT NULL, 
    `likes` int(11) NOT NULL, 
    `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', 
    PRIMARY KEY (`id`), 
    // Foreign key stuff 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 

Przykładowe dane

INSERT INTO `language_page_likes_history` (`id`, `language_page_likes_id`, `likes`, `created_at`) 
VALUES 
    (1, 1, 3272484, '2015-09-11 08:40:23'), 
    (132014, 1, 3272827, '2015-09-14 08:31:00'), 
    (2, 2, 1581361, '2015-09-11 08:40:23'), 
    (132015, 2, 1580392, '2015-09-14 08:31:00'), 
    (3, 3, 1467090, '2015-09-11 08:40:23'), 
    (132016, 3, 1467329, '2015-09-14 08:31:00'), 
    (47, 47, 828736, '2015-09-11 08:40:23'), 
    (132060, 47, 828971, '2015-09-14 08:31:00'), 
    (51, 51, 602747, '2015-09-11 08:40:23'), 
    (132064, 51, 603071, '2015-09-14 08:31:00'), 
    (53, 53, 545484, '2015-09-11 08:40:23'), 
    (132066, 53, 545092, '2015-09-14 08:31:00'), 
    (92, 92, 916570, '2015-09-11 08:40:24'), 
    (5, 92, 917032, '2015-09-14 08:31:01'), 
    (95, 95, 537382, '2015-09-11 08:40:24'), 
    (8, 95, 537395, '2015-09-14 08:31:01'), 
    (97, 97, 419175, '2015-09-11 08:40:24'), 
    (132110, 97, 419484, '2015-09-14 08:31:01'); 

Jak widać, mam dane dla 14 i 11 września. Teraz chcę uzyskać stronę, z największym wzrostem polubień. Zanim zrobię to za pomocą kolumny o nazwie last_like_count, ale problem polega na tym, że nie mogę być dynamiczny w zakresie dat. Dzięki "normalnej" funkcji regresji mogę być dynamiczny dla każdego zakresu dat.

Rozwiązanie znalezienie
Co już udało się zrobić, było zbudowanie wszystkie relacje, które są obecne

SELECT p.id, p.facebook_name, plh.likes, l.language FROM facebook_pages p 
INNER JOIN language_page_likes pl ON pl.facebook_page_id = p.id 
INNER JOIN language_page_likes_history plh ON plh.language_page_likes_id = pl.id 
INNER JOIN languages l ON l.id = pl.language_id 
WHERE pl.language_id = 5 OR pl.language_id = 46 OR pl.language_id = 68 

Z tego zapytania dostaję za każdym likecount w historii systemu specyficzny Języki. Ale w jaki sposób zbudowałbym analizę regresji w tej części?

ja już znalazłem ten link tutaj

Identifying trend with SQL query

ale moje umiejętności matematyczne i MySQL nie są wystarczająco wysokie, aby przetłumaczyć SQL w MySQL. Jakaś pomoc?

+1

to dość proste, jeśli RDBMS obsługuje funkcje okienkowe (jak w linku pisał), ale niestety, MySQL brakuje wielu funkcji, które mają inne RDBMS. Najbardziej sensownym rozwiązaniem byłoby przejście na RDBMS, który obsługuje funkcje okienkowania (np. PostgreSQL). –

+2

Przełączanie RDBMS jest najrozsądniejszym rozwiązaniem do rozwiązania pojedynczego pytania analizy danych? – rwking

Odpowiedz

5

To może być to, czego szukasz:

SELECT SUM((X-AVG_X)*(Y-AVG_Y))/SUM((X-AVG_X)*(X-AVG_X)) AS Slope, 
     PageId, LanguageId 
FROM 
(
SELECT Q0.Y, 
     Q0.X, 
     Q1.AVG_Y, 
     Q1.AVG_X, 
     Q1.PageId, 
     Q1.LanguageId 
FROM (SELECT T0.likes AS Y, 
       UNIX_TIMESTAMP(T0.created_at) AS X, 
       T1.facebook_page_id AS PageId, 
       T1.language_id AS LanguageId 
     FROM language_page_likes_history T0 INNER JOIN 
       language_page_likes T1 ON 
       (T0.language_page_likes_id = T1.id) 
     WHERE T0.created_at > '2015-09-11 00:00:00' AND 
       T0.created_at < '2015-09-15 00:00:00') Q0 INNER JOIN 
     (SELECT AVG(T2.likes) AS AVG_Y, 
       AVG(UNIX_TIMESTAMP(T2.created_at)) AS AVG_X, 
       T3.facebook_page_id AS PageId, 
       T3.language_id AS LanguageId 
     FROM language_page_likes_history T2 INNER JOIN 
       language_page_likes T3 ON 
       (T2.language_page_likes_id = T3.id) 
     WHERE T2.created_at > '2015-09-11 00:00:00' AND 
       T2.created_at < '2015-09-15 00:00:00' 
     GROUP BY T3.facebook_page_id, T3.language_id) Q1 
     ON (Q0.PageId = Q1.PageId) AND (Q0.LanguageId = Q1.LanguageId) 
) Q2 
GROUP BY PageId, LanguageId 
ORDER BY Slope DESC 

Zwraca nachylenie regresji liniowej na stronę i Języka. Kolumna Slope przedstawia liczbę polubień na sekundę. W Twoich przykładowych danych ilość podobieństw maleje w dwóch przypadkach. Nie wiem dlaczego. Wynik powinien wyglądać tak. Instrukcja SQL jest testowana i ręcznie sprawdziłem obliczenia w dwóch rzędach dla prawidłowego wyniku.

|   Slope | PageId | LanguageId | 
|-----------------|--------|------------| 
| 0.001786287345 |  3 |   3 | 
| 0.001326183029 |  1 |   1 | 
| 0.001252720995 |  2 |   1 | 
| 0.001194724653 |  3 |   1 | 
| 0.000924075055 |  1 |   3 | 
| 0.000908609364 |  2 |   3 | 
| 0.000050263497 |  3 |   2 | 
| -0.001515637747 |  2 |   2 | 
| -0.003746563717 |  1 |   2 | 

Możliwe, że wystąpił problem, jeśli w tabelach nie ma danych. Więc być może ISNULL-kontrole muszą być dodane.


Gdy chcesz poznać tylko wartości bezwzględne, jest to prostsze. Możesz pobrać następujące oświadczenie:

SELECT PageId, LanguageId, 
     (likes_last_in_period - likes_before_period) AS Likes 
FROM 
(SELECT T1.facebook_page_id AS PageId, 
     T1.language_id AS LanguageId, 
     (SELECT likes 
     FROM language_page_likes_history 
     WHERE created_at < '2015-09-12 00:00:00' AND 
       language_page_likes_id = T1.id 
     ORDER BY created_at DESC LIMIT 1) likes_before_period, 
     (SELECT likes 
     FROM language_page_likes_history 
     WHERE created_at >= '2015-09-12 00:00:00' AND 
       language_page_likes_id = T1.id 
     ORDER BY created_at ASC LIMIT 1) likes_first_in_period, 
     (SELECT likes 
     FROM language_page_likes_history 
     WHERE created_at <= '2015-09-15 00:00:00' AND 
       language_page_likes_id = T1.id 
     ORDER BY created_at DESC LIMIT 1) likes_last_in_period, 
     (SELECT likes 
     FROM language_page_likes_history 
     WHERE created_at > '2015-09-15 00:00:00' AND 
       language_page_likes_id = T1.id 
     ORDER BY created_at ASC LIMIT 1) likes_after_period 

     FROM language_page_likes T1) Q0 
ORDER BY Likes DESC 

, które ma 4 zapytania dodatkowe. Potrzebne są tylko dwie, które musisz wybrać. Zdecydowałem się użyć liczby polubień tuż przed okresem i ostatnią liczbą polubień, która jest w okresie do obliczenia różnicy. Wynik wygląda tak:

| PageId | LanguageId | Likes | 
|--------|------------|-------| 
|  3 |   3 | 462 | 
|  1 |   1 | 343 | 
|  2 |   1 | 324 | 
|  3 |   1 | 309 | 
|  1 |   3 | 239 | 
|  2 |   3 | 235 | 
|  3 |   2 | 13 | 
|  2 |   2 | -392 | 
|  1 |   2 | -969 | 
+0

To jest super niesamowite. 1 upvote jest dla Ciebie gwarantowane. Ale nie chciałem tego, co na sekundę, przepraszam, jeśli to nie było jasne. Chcę zobaczyć wzrost liczby polubień w okresie daty. Przykład: Ile polubień stronstrony 3 uzyskał w ciągu ostatnich 7 dni. (Zmniejszenie może być, ponieważ ludzie z tego kraju nie lubią lub zmieniają języki?) – Musterknabe

+0

Tak, twoje pytanie nie było jasne, mówiłeś o analizie regresji i łączyłeś inną odpowiedź, która również implementuje formalnie regresję liniową. Uzyskanie wartości bezwzględnych jest znacznie prostsze. Zobacz moje zmiany ... – user1027167

+0

Jeśli zrozumiałem to poprawnie. To zapytanie pokazuje teraz, ile osób polubiło stronę zaginioną dla określonego języka między dwiema datami, 12 września i 15 września, prawda? Jeśli tak, przyjmuję twoją odpowiedź – Musterknabe

2

To właśnie mogłem wymyślić w tej chwili. Nie mogę poprawnie przetestować tego zapytania, ponieważ teraz nie mam czasu na tworzenie tych struktur tabel na jednej ze stron testowych sql sieci. Ale myślę, że nawet jeśli początkowo nie działa, może wskazać ci właściwy kierunek.

select 
    id, 
    new_date, 
    max(increase) 
from (
select 
    dg.id, 
    dg.date new_date, 
    dg.sum - (select sum from dg where dg.date = date_format((date_sub(str_to_date(new_date, '%Y-%m-%d') 1 DAY), '%Y-%m-%d') increase 
from (
select 
    language_pages_likes_id id, 
    date_format(created_at, '%Y%-m$-%d') date, 
    sum(likes) likes_sum 
from 
    language_page_likes_history lplh 
group by 
    language_page_likes_id, 
    date_format(created_at, '%Y%-m$-%d') 
) day_grouping dg 
) calculate_increases 

Mam nadzieję, że to pomaga. Później, kiedy będę mógł, będę dalej testować i ulepszać to zapytanie.