Controlli logici e problemi di performance all'interno di un conteggio (distinto foo)
-
23-12-2019 - |
Domanda
Ho una domanda regolare e molto costosa che devo correre, e sfortunatamente devo unirmi ai risultati di quella query con quasi esattamente la stessa query per ottenere un rapporto ... con conseguente uso di una query che prende il sopravvento 3 minuti da eseguire. Questo è quello che vorrei fare .... (supponendo che evitasse un join accederebbe il tempo di query)
SELECT
date,
meal,
country,
COUNT(DISTINCT person, WHERE UPPER(ingredient) CONTAINS "SUN BUTTER", 10000000) as total_sunbutter_meals_per_day
COUNT(DISTINCT person, 10000000) as total_meals
ROUND(100*total_sunbutter_meals_per_day/total_meals,1) as percentage_meals_sunbutter
FROM [project:dataset.menu]
GROUP BY date, meals, country
.
Questo è ciò che sono costretto a fare ....
SELECT
total.date as date,
total.meal as meal,
total.country as country,
total_sunbutter_meals_per_day,
total_meals_per_day,
ROUND(100*total_sunbutter_meals_per_day/total_meals,1) as percentage_meals_sunbutter
FROM
(
SELECT
date,
meal,
country,
COUNT(DISTINCT person, 100000) as total_sunbutter_meals_per_day
FROM [project:dataset.menu]
WHERE
UPPER(ingredient) CONTAINS "SUN BUTTER"
GROUP BY date, meals, country
) as sunbutter
JOIN
(
SELECT
date,
meal,
country,
COUNT(DISTINCT person, 100000) as total_meals_per_day
FROM [project:dataset.menu]
GROUP BY date, meals, country
) as total
ON total.date = sunbutter.date AND total.meal = sunbutter.meal AND total.country = sunbutter.country
.
Tre problemi / domande:
- .
- Sembra che ci sia un modo in cui la grossa query potrebbe eseguire un conteggio (campo distinto) con una logica condizionale incorporata. C'è un modo per evitare di fare un join in questo scenario sopra?
- Count distinto con un valore superiore a 100.000 ha fallito per me. Mi piacerebbe essere in grado di fare un conteggio distinto di 10.000.000. Ci sono noti problemi di performance con il conteggio distinto e valori di grandi dimensioni? È questo essere indirizzato?
-
Ci sono piani per poter utilizzare il nome del campo dichiarato / calcolato all'interno della selezione in un'altra istruzione in quella selezione? Nell'esempio migliore, vorrei usare i nomi per i risultati invece di ripetere la formula nella dichiarazione rotonda. (cioè mi piacerebbe specificare
total_sunbutter_meals_per_day / total_meals Invece di
conteggio (persona distinta, dove superiore (ingrediente) contiene "burro di sole", 100000) / conteggio (persona distinta, 10000000)
Grazie in anticipo per l'aiuto!
Soluzione
Domanda 1:
È possibile creare una query interiore con due campi distinti come segue:
SELECT date, meal, country, COUNT(DISTINCT person) total_meals, COUNT(DISTINCT sunbutter_person) total_sunbutter_meals, FROM (SELECT date, meal, country, person, IF(UPPER(ingredient) CONTAINS "SUN BUTTER", person, NULL) sunbutter_person FROM [project:dataset.menu]).
Domanda 2:
In BigQuery, il conteggio (distinto) restituisce un risultato approssimativo. Se si aumenta la soglia in cui vengono restituiti i risultati precisi, avrai danneggiato le prestazioni (e alla fine causare il fallimento della tua query) perché un singolo lavoratore deve tenere traccia di tutti questi valori distinti. Vedi conteggio bigquery (valore distinto) VS Count (valore) per ulteriori informazioni. .
Se la necessità di risultati precise in ottimalità del conteggio (distinto) è la scalabilità, l'alternativa è quella di utilizzare il gruppo ciascuno con il conteggio (*), che ti darà conteggi precisi per elementi distinti in modo scalabile.
Nota che dovrai affrontare il problema in questione 1 in un modo leggermente diverso. Qualcosa come:
SELECT date, meal, country, COUNT(*) total_meals, SUM(sunbutter) total_sunbutter_meals, FROM (SELECT date, meal, country, IF(UPPER(ingredient) CONTAINS "SUN BUTTER", 1, 0) sunbutter, FROM [project:dataset.menu] GROUP EACH BY date, meal, country, person) GROUP BY date, meal, country.
Domanda 3:
In questo momento, non è possibile fare riferimento ad altri campi nella stessa istruzione SELECT, e non abbiamo ancora intenzione di aggiungere questa funzione. Ma puoi sempre avvolgere la tua query in un'altra query.
invece di:
SELECT 17 AS a, a + 1 AS b.
Puoi scrivere:
SELECT a, a + 1 AS b FROM (SELECT 17 AS a).