web-dev-qa-db-ja.com

行の総数と選択された(集計された)データを返す

テーブルからデータを選択する機能があります。選択したデータとそのテーブルの行の総数を返したいのですが。

どうすればそれを行うことができますか、または最も効率的な方法で同じ結果を得るにはどうすればよいですか?

私はいくつかのことを試しましたが、以下のコードで終わりました、これは私が望む形式ですが、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

更新されました、以下のコードは私が望む結果を生み出しています、それを隠すことができればいいです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
5
RockNinja

質問を理解しているので、ウィンドウ関数は必要ありません。集約関数がその役割を果たします。

  • 最下位レベルの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;_

_landing_path_id_も含めたので、結果のデータは意味があります。

SQLフィドル

ウィンドウ関数?

集計されていない行がないため、ウィンドウ関数(count(*) over ())は期待どおりではないようです。
あなたが内部サブクエリに追加できます

_count(*) OVER ()
_

..興味深い__landing_path_id_のカウントを取得する。しかし、それは「そのレコードが選択したレコードの合計行数」が意図したものではないようです。
または、あなたが内部サブクエリに追加できます

_sum(count(*)) OVER ()
_

..すべての_landing_path_id_の合計数を冗長に取得しますが、それは無意味に思えます。これを説明するために、単一パスで集計関数の結果に対してウィンドウ関数を実行することは可能であることを述べました。その詳細:

更新された質問

recordsサブクエリに_total_count_を含まない結果。内側のLIMITSELECTを考慮に入れます。最大10個の異なる_landing_path_id_が選択されている場合でも、all修飾_landing_path_id_がカウントされます。

1回のスキャンで両方を取得し、カウントを再利用して個別に合計するには、[〜#〜] 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;_

属性名を気にしない場合は、サブクエリを使用してcheaperにすることができます。

_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;_

entrances式は列名を保持しないため、ROWではなくデフォルトの属性名_f1_を取得します。

特定の属性名が必要な場合行を登録済みの型にキャストできます。 (Ab-)_TEMP TABLE_を使用して、セッションの行タイプを登録します。

_CREATE TEMP TABLE rec1 (entrances bigint);

...
        , array_to_json(array_agg(row_to_json(ROW(entrances)::rec1))) AS data
..._

これは、CTEよりも少し高速です。または、より詳細ですがキャストなし

_...
        , array_to_json(array_agg(row_to_json(
                   (SELECT x FROM (SELECT records.entrances) x)))) AS data
..._

この関連する回答の詳細な説明:

SQLフィドル

6

あなたはa_horse_with_no_nameまたはForguesRが提案したことを実行できます(私はa_horse_with_no_nameの提案がForguesRよりも効率的だと思います)。しかし、これらは結果セットに追加の列を提供します。それは、その追加の列が必要かどうか(すべて同じデータが繰り返されることを示す)か、「要約行」のような結果セット内の行が必要かどうかに依存します。

「要約行」タイプの結果に関心がある場合は、私の回答で対処します。

別のオプションは、探しているCOUNT(*)を提供するクエリを作成し、元のクエリでそれをUNIONすることです。もちろん、これの秘訣は、両方のクエリに同じ数の列があり、COUNT(*)クエリが最後になることを確認することです。そのために、並べ替えに使用する列を追加しました。以下の簡単な例を参照してください。

-- 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;
2
Joishi Bodio

テーブルのすべての行の数を取得するには、サブクエリを含めるだけです。何かのようなもの :

SELECT *, (SELECT COUNT(*) FROM yourTable) AS TotalNbRows FROM yourTable
1
ForguesR

集計クエリをサブクエリに入れます

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
0
Ali Azhar