Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Znajdowanie unikalnych użytkowników z powiązanych wartości

Chciałem wskoczyć z opcją rozwiązania swojego zadania za pomocą czystego BigQuery (Standard SQL)

Warunki wstępne/założenia :dane źródłowe znajdują się w sandbox.temp.id1_id2_pairs
Powinieneś to zastąpić własnym lub jeśli chcesz przetestować z fikcyjnymi danymi ze swojego pytania - możesz utworzyć tę tabelę jak poniżej (oczywiście zastąp sandbox.temp z własnym project.dataset )


Upewnij się, że ustawiłeś odpowiednią tabelę docelową

Uwaga :możesz znaleźć wszystkie odpowiednie zapytania (jako tekst) na dole tej odpowiedzi, ale na razie ilustruję moją odpowiedź zrzutami ekranu - więc wszystko jest przedstawione - zapytanie, wynik i użyte opcje

Tak więc będą trzy kroki:

Krok 1 — Inicjalizacja

Tutaj po prostu robimy wstępne grupowanie id1 na podstawie połączeń z id2:

Jak widać tutaj - stworzyliśmy listę wszystkich wartości id1 z odpowiednimi połączeniami w oparciu o proste jednopoziomowe połączenie przez id2

Tabela wyjściowa to sandbox.temp.groups

Krok 2 — Grupowanie iteracji

W każdej iteracji będziemy wzbogacać grupowanie na podstawie już ustalonych grup.
Źródłem zapytania jest wyjściowa tabela z poprzedniego kroku (sandbox.temp.groups ) i Destination to ta sama tabela (sandbox.temp.groups ) z nadpisaniem

Będziemy kontynuować iteracje, aż liczba znalezionych grup będzie taka sama jak w poprzedniej iteracji

Uwaga :możesz po prostu otworzyć dwie karty internetowego interfejsu użytkownika BigQuery (jak pokazano powyżej) i bez zmiany kodu, po prostu uruchom Grupowanie, a następnie sprawdzaj raz za razem, aż iteracja zbiegnie się

(dla konkretnych danych, których użyłem w sekcji wymagań wstępnych - miałem trzy iteracje - pierwsza iteracja dała 5 użytkowników, druga iteracja dała 3 użytkowników, a trzecia iteracja dała ponownie 3 użytkowników - co wskazuje, że zrobiliśmy z iteracjami.

Oczywiście w prawdziwym przypadku - liczba iteracji może być większa niż tylko trzy - więc potrzebujemy pewnego rodzaju automatyzacji (patrz odpowiedni rozdział na dole odpowiedzi).

Krok 3 – Ostateczne grupowanie
Po zakończeniu grupowania id1 - możemy dodać końcowe grupowanie dla id2

Ostateczny wynik jest teraz w sandbox.temp.users tabela

Użyte zapytania (nie zapomnij ustawić odpowiednich tabel docelowych i nadpisać w razie potrzeby zgodnie z opisaną powyżej logiką i zrzutami ekranu):

Wymagania wstępne:

#standardSQL
SELECT 1 id, 'e1' id1, 'm1' id2 UNION ALL
SELECT 2,    'e1',     'm2' UNION ALL
SELECT 3,    'e2',     'm2' UNION ALL
SELECT 4,    'e3',     'm1' UNION ALL
SELECT 5,    'e4',     'm3' UNION ALL
SELECT 6,    'e5',     'm3' UNION ALL
SELECT 7,    'e5',     'm4' UNION ALL
SELECT 8,    'e4',     'm5' UNION ALL
SELECT 9,    'e6',     'm6' UNION ALL
SELECT 9,    'e7',     'm7' UNION ALL
SELECT 9,    'e2',     'm6' UNION ALL
SELECT 888,  'e4',     'm55'   

Krok 1

#standardSQL
WITH `yourTable` AS (select * from `sandbox.temp.id1_id2_pairs`
), x1 AS (SELECT id1, STRING_AGG(id2) id2s FROM `yourTable` GROUP BY id1
), x2 AS (SELECT id2, STRING_AGG(id1) id1s FROM `yourTable` GROUP BY id2 
), x3 AS (
  SELECT id, (SELECT STRING_AGG(i ORDER BY i) FROM (
    SELECT DISTINCT i FROM UNNEST(SPLIT(id1s)) i)) grp
  FROM (
    SELECT x1.id1 id, STRING_AGG((id1s)) id1s FROM x1 CROSS JOIN x2
    WHERE EXISTS (SELECT y FROM UNNEST(SPLIT(id1s)) y WHERE x1.id1 = y)
    GROUP BY id1) 
)
SELECT * FROM x3 

Krok 2 - Grupowanie

#standardSQL
WITH x3 AS (select * from `sandbox.temp.groups`)
SELECT id, (SELECT STRING_AGG(i ORDER BY i) FROM (
  SELECT DISTINCT i FROM UNNEST(SPLIT(grp)) i)) grp
FROM (
  SELECT a.id, STRING_AGG(b.grp) grp FROM x3 a CROSS JOIN x3 b 
  WHERE EXISTS (SELECT y FROM UNNEST(SPLIT(b.grp)) y WHERE a.id = y)
  GROUP BY a.id )   

Krok 2 - Sprawdź

#standardSQL
SELECT COUNT(DISTINCT grp) users FROM `sandbox.temp.groups` 

Krok 3

#standardSQL
WITH `yourTable` AS (select * from `sandbox.temp.id1_id2_pairs`
), x1 AS (SELECT id1, STRING_AGG(id2) id2s FROM `yourTable` GROUP BY id1 
), x3 as (select * from `sandbox.temp.groups`
), f  AS (SELECT DISTINCT grp FROM x3 ORDER BY grp
)
SELECT ROW_NUMBER() OVER() id, grp id1, 
  (SELECT STRING_AGG(i ORDER BY i) FROM (SELECT DISTINCT i FROM UNNEST(SPLIT(id2)) i)) id2
FROM (
  SELECT grp, STRING_AGG(id2s) id2 FROM f 
  CROSS JOIN x1 WHERE EXISTS (SELECT y FROM UNNEST(SPLIT(f.grp)) y WHERE id1 = y)
  GROUP BY grp)

Automatyzacja :
Oczywiście, powyższy "proces" można wykonać ręcznie w przypadku, gdy iteracje szybko się zbiegają - w rezultacie otrzymasz 10-20 przebiegów. Ale w bardziej rzeczywistych przypadkach możesz to łatwo zautomatyzować z dowolnym klientem do wyboru




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak przechowywać zamówienia?

  2. json_encode i highcharts

  3. MYSQL odróżnia wpis dwóch kolumn nawet po przełączeniu

  4. Ile wpisów znajduje się w węźle B-drzewa indeksu MySQL?

  5. Baza danych MySQL nie może się uruchomić na XAMPP dla Mac