2016-10-28 3 views
2

J'essaie de trouver le nombre distinct d'utilisateurs américains ayant effectué une action spécifique (n'importe quelle ligne dans p.action) dans une fenêtre de 14 jours , au cours des deux derniers mois.Comment supprimer la sous-requête corrélée dans ma sous-sélection (en raison de la limitation presto)

Voici la requête. J'aimerais avoir quelques conseils sur la façon dont je peux réécrire cela pour ne pas utiliser une sous-requête corrélée, car Presto ne les autorise pas.

SELECT dt, 
    (SELECT COUNT(DISTINCT user_id) 
    FROM p.action 
    WHERE dt BETWEEN q.dt - 13 AND q.dt -- period of 14 days 
     AND country = 'US' 
    ) AS 14d_rolling_users 
FROM p.action q 
WHERE dt BETWEEN '2016-08-24' AND '2016-10-24' 
GROUP BY dt 
ORDER BY dt ASC 

Je suis creusé la tête à essayer de comprendre comment je pouvais accomplir cela sans courir juste 60 requêtes individuelles (un pour chaque jour).

Toute aide appréciée, merci!

Répondre

1

Ne pas avoir l'expérience avec presto, mais logiquement, vous pouvez réécrire votre requête pour faire un produit cartésien se joindre (joindre sans conditions) de p.action avec des contraintes de date 2 mois avec p.action avec les mêmes contraintes de date 2 papillons de nuit, puis vous n'auriez pas besoin de la requête interne.

SELECT dt,COUNT(DISTINCT user_id) 
FROM p.action q1,p.action q2 
WHERE q1.dt BETWEEN '2016-08-24' AND '2016-10-24' 
    AND q2.dt BETWEEN '2016-08-24' AND '2016-10-24' 
    AND q1.dt BETWEEN q2.dt - 13 AND q2.dt -- period of 14 days 
    AND country = 'US' 
GROUP BY q1.dt 
ORDER BY q1.dt ASC 

Il serait plus efficace de créer la table de 2 mois au préalable - ici les conditions sont appliquées après la jointure.

0

Depuis 0.153, Presto contient un support initial pour les sous-requêtes corrélées. (Voir https://prestodb.io/docs/current/release/release-0.153.html).

Votre requête doit passer si vous pouvez omettre DISTINCT

SELECT dt, 
    (SELECT COUNT(user_id) 
    FROM p.action 
    WHERE dt BETWEEN q.dt - 13 AND q.dt -- period of 14 days 
     AND country = 'US' 
    ) AS 14d_rolling_users 
FROM p.action q 
WHERE dt BETWEEN '2016-08-24' AND '2016-10-24' 
GROUP BY dt 
ORDER BY dt ASC 

Je sais que rewrite ci-dessus a complètement différent sémantique que votre requête initiale. Mais j'espère que cela vous donnera une idée de ce qui est autorisé dans Presto, afin que vous puissiez réécrire votre requête comme vous le souhaitez.

De toute façon, j'ai créé un problème pour cela. J'espère que cela va bientôt se corriger. Voir https://github.com/prestodb/presto/issues/6480.

0

Meilleur faire un rollup manuel.

Cela transforme chaque ligne de votre table en 14 lignes avec des horodatages supplémentaires rollup__ds. Nous regroupons ensuite par cette nouvelle colonne pour créer une fenêtre mobile de 14 jours. La complexité de ceci est O(N*14) = O(N) et donc linéaire.

SELECT 
    rollup__ds, 
    COUNT(DISTINCT username) 
FROM (
    SELECT 
    username, 
    ds 
    FROM 
    actions 
    WHERE 
    ds BETWEEN '2016-08-24' AND '2016-10-24' 
    AND country = 'US' 
) 
CROSS JOIN 
    UNNEST(ARRAY[ 
    DATE_ADD('day', 0, CAST(ds AS DATE)), 
    DATE_ADD('day', 1, CAST(ds AS DATE)), 
    ... 
    DATE_ADD('day', 12, CAST(ds AS DATE)), 
    DATE_ADD('day', 13, CAST(ds AS DATE)) 
    ]) AS t (rollup__ds) 
GROUP BY 
    rollup__ds 
ORDER BY 
    rollup__ds 
; 

Hope that helps!


NB- si vous n'avez pas besoin compte distinct mieux utiliser une fonction de fenêtre, hélas cela ne fonctionne pas pour compte distinct parce qu'ils ne sont pas SOMMABLE comme ça.

SELECT 
    ds, 
    -- BEWARE this count is NOT distinct! 
    SUM(COUNT(username)) over (ORDER BY ds ROWS BEWTEEN 13 PRECEDING AND CURRENT ROW) 
FROM 
    actions 
WHERE 
    ds BETWEEN '2016-08-24' AND '2016-10-24' 
    AND country = 'US' 
;