返回总行数和选定(聚合)数据

Roc*_*nja 6 postgresql aggregate window-functions postgresql-9.3

我有一个从表格中选择一些数据的功能。我想返回所选数据和该表中的总行数。

我怎样才能做到这一点,或者我怎样才能以最有效的方式获得相同的结果?

我尝试了几件事,最后得到了下面的代码,现在这是我想要的格式,但count(*) over () as total_count会一直返回 1,我需要它返回的是该records选择的总行数。

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
Run Code Online (Sandbox Code Playgroud)

更新,下面的代码产生了我想要的结果,如果我可以total_countrecords选择中隐藏该列就好了

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
Run Code Online (Sandbox Code Playgroud)

Erw*_*ter 6

据我了解,您不需要窗口函数。聚合函数完成这项工作:

  • count()在最低级别 (-> row_ct)。
  • sum()结果row_ct在下一个级别 (-> 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;
Run Code Online (Sandbox Code Playgroud)

我也包括在内,landing_path_id所以结果数据是有道理的。

SQL小提琴。

窗函数?

窗口函数 ( count(*) over ()) 似乎不是您想要的,因为您没有未聚合的行。
可以添加到内部子查询:

count(*) OVER ()
Run Code Online (Sandbox Code Playgroud)

.. 获得 distinct 的计数landing_path_id,这是另一个可能感兴趣的数字。但这似乎不是您所说的“该记录选择的总行数”的意思。
或者您可以添加到内部子查询:

sum(count(*)) OVER ()
Run Code Online (Sandbox Code Playgroud)

.. 获得每个landing_path_id冗余的总数,但这似乎毫无意义。只是提到为了演示可以在一次传递中对聚合函数的结果运行窗口函数。详情:

更新的问题

您的结果,只是没有total_countrecords子查询中。现在占LIMIT了内部SELECT。即使最多landing_path_id选择了 10 个不同的,但所有符合条件的landing_path_id都被计算在内。

为了同时获得一次扫描和重用计数和总和,我引入了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;
Run Code Online (Sandbox Code Playgroud)

如果您不关心属性名称,则可以使用子查询更便宜

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;
Run Code Online (Sandbox Code Playgroud)

您将获得默认属性名称f1而不是entrances,因为ROW表达式不保留列名称。

如果您需要某个属性名称,您可以将该行转换为注册类型。(Ab-) 使用 aTEMP TABLE为会话注册我的行类型:

CREATE TEMP TABLE rec1 (entrances bigint);

...
        , array_to_json(array_agg(row_to_json(ROW(entrances)::rec1))) AS data
...
Run Code Online (Sandbox Code Playgroud)

这会比 CTE 快一点。或者,更详细但没有强制转换

...
        , array_to_json(array_agg(row_to_json(
                   (SELECT x FROM (SELECT records.entrances) x)))) AS data
...
Run Code Online (Sandbox Code Playgroud)

此相关答案中的详细说明:

SQL小提琴。