J'ai une fonction qui sélectionne certaines données d'une table. Je souhaite renvoyer les données sélectionnées et le nombre total de lignes dans ce tableau.
Comment puis-je faire cela ou comment obtenir le même résultat de la manière la plus efficace?
J'ai essayé peu de choses et je me suis retrouvé avec le code ci-dessous, maintenant c'est le format que je veux, mais count(*) over () as total_count
retournera 1 tout le temps, ce dont j'ai besoin pour retourner est le nombre total de lignes à partir de ce records
sélectionnez.
SELECT
row_to_json(selected_records) as data
FROM
(
SELECT
count(*) over () as total_count,
array_to_json(array_agg(row_to_json(records))) as data
FROM (
SELECT
sum(entrances) as entrances
FROM report_la
WHERE profile_id = 3777614
GROUP BY landing_path_id
limit 10 offset 0
) records
) as selected_records
Mis à jour, le code ci-dessous produit le résultat que je veux, ce sera bien si je peux cacher ça total_count
dans la colonne records
sélectionnez
SELECT
row_to_json(selected_records) as data
FROM
(
SELECT
min(total_count) as total_count
,array_to_json(array_agg(row_to_json(records))) as data
FROM (
SELECT
sum(entrances) as entrances
,count(*) over () as total_count
FROM ga.report_la
WHERE ga_profile_id = 3777614
GROUP BY landing_path_id
limit 10
) records
) as selected_records
Si je comprends bien la question, vous n'avez pas besoin d'une fonction de fenêtre. Les fonctions d'agrégation font le travail:
count()
au niveau le plus bas (-> row_ct
).sum()
le row_ct
résultant au niveau suivant (-> total_row_ct
).SELECT row_to_json(selected_records)::text AS data
FROM (
SELECT array_to_json(array_agg(row_to_json(records))) AS data
, sum(row_ct) AS total_row_ct
FROM (
SELECT landing_path_id
, sum(entrances) AS entrances
, count(*) AS row_ct
FROM report_la
WHERE profile_id = 3777614
GROUP BY landing_path_id
LIMIT 10
) records
) selected_records;
J'ai également inclus landing_path_id
Afin que les données résultantes aient du sens.
Une fonction de fenêtre (count(*) over ()
) ne semble pas être ce que vous voulez, car vous n'avez pas de lignes non agrégées.
Vous pourriez ajouter à la sous-requête interne:
count(*) OVER ()
.. pour obtenir le nombre de landing_path_id
distincts, qui est un autre nombre possible qui pourrait être intéressant. Mais cela ne semble pas être ce que vous vouliez dire par "le nombre total de lignes de ces enregistrements sélectionnés".
Ou vous pourriez ajouter à la sous-requête interne:
sum(count(*)) OVER ()
.. pour obtenir le nombre total avec chaque landing_path_id
redondant, mais cela semblerait inutile. Il suffit de mentionner que pour démontrer qu'il est possible d'exécuter une fonction de fenêtre sur le résultat d'une fonction d'agrégation en une seule passe. Détails pour cela:
Votre résultat, juste sans total_count
Dans la sous-requête records
. Comptant maintenant le LIMIT
dans le SELECT
intérieur. Même si un maximum de 10 landing_path_id
Distincts est sélectionné, touslanding_path_id
Éligibles sont comptés.
Pour obtenir les deux en un seul scan et réutiliser le nombre et la somme séparément, j'introduis un [~ # ~] cte [~ # ~] :
WITH cte AS (
SELECT sum(entrances) AS entrances
, count(*) over () AS total_count
FROM report_la
WHERE profile_id = 3777614
GROUP BY landing_path_id
LIMIT 10
)
SELECT row_to_json(selected_records)::text AS data
FROM (
SELECT (SELECT total_count FROM cte LIMIT 1) AS total_count
, array_to_json(array_agg(row_to_json(records))) AS data
FROM (SELECT entrances FROM cte) records
) selected_records;
Si vous ne vous souciez pas du nom de l'attribut, vous pouvez avoir moins cher avec une sous-requête:
SELECT row_to_json(selected_records)::text AS data
FROM (
SELECT min(total_count) AS total_count
, array_to_json(array_agg(row_to_json(ROW(entrances)))) AS data
FROM (
SELECT sum(entrances) AS entrances
, count(*) over () AS total_count -- shouldn't show up in result
FROM report_la
WHERE profile_id = 3777614
GROUP BY landing_path_id
LIMIT 1
) records
) selected_records;
Vous obtenez le nom d'attribut par défaut f1
Au lieu de entrances
, car l'expression ROW
ne conserve pas le nom de la colonne.
Si vous avez besoin d'un certain nom d'attribut , vous pouvez convertir la ligne en un type enregistré . (Ab-) en utilisant un TEMP TABLE
Pour enregistrer mon type de ligne pour la session:
CREATE TEMP TABLE rec1 (entrances bigint);
...
, array_to_json(array_agg(row_to_json(ROW(entrances)::rec1))) AS data
...
Ce serait un peu plus rapide que le CTE. Ou, plus verbeux mais sans transtypage :
...
, array_to_json(array_agg(row_to_json(
(SELECT x FROM (SELECT records.entrances) x)))) AS data
...
Explication détaillée dans cette réponse connexe:
Vous pouvez faire ce que a_horse_with_no_name ou ForguesR a suggéré (je pense que la suggestion de a_horse_with_no_name est plus efficace que ForguesR) .. Cependant, ceux-ci vous donneront une colonne supplémentaire dans votre jeu de résultats - que vous souhaitiez ou non. Cela dépend en quelque sorte si vous voulez que cette colonne supplémentaire (affichant toutes les mêmes données répétées) ou si vous voulez une ligne dans votre jeu de résultats qui soit semblable à une "ligne récapitulative".
Ma réponse s'adressera si vous êtes intéressé par un type de résultat "résumé".
Une autre option serait d'avoir une requête qui vous donne la COUNT(*)
que vous recherchez, puis UNION
avec votre requête d'origine. L'astuce pour cela, bien sûr, est de vous assurer que vous avez le même nombre de colonnes dans les deux requêtes et que la requête COUNT(*)
se termine en dernier. Pour ce faire, j'ai ajouté une colonne qui permet de trier par .. Voir l'exemple simple ci-dessous.
-- assume col1, col2 are VARCHAR and col3, col4 are NUMERIC
SELECT
col1, col2, col3, col4
FROM (
SELECT
col1, col2, col3, col4, 1 AS sorter
FROM tab1
UNION
SELECT
NULL::VARCHAR AS col1, NULL::VARCHAR AS col2, NULL::NUMERIC AS col3, COUNT(*) AS col4, 2 AS sorter
FROM tab1
) a
ORDER BY a.sorter, a.col1, a.col2;
Il vous suffit d'inclure une sous-requête pour obtenir le nombre de toutes les lignes de votre table. Quelque chose comme :
SELECT *, (SELECT COUNT(*) FROM yourTable) AS TotalNbRows FROM yourTable
Mettez votre requête agrégée en sous-requête
SELECT COUNT( * )
FROM (
SELECT COUNT( * ) AS `count`
FROM lms
WHERE `lead_school_type` =3
AND subscription.vad =1
GROUP BY lms.user_id
) AS subcount