1

私は一般的にSQLの経験が豊富ではなく、かなり具体的なタスクを達成しようとしています-最初にクエリを実行して、ヒット数が上位のすべてのユニットのIDを取得し、次にその実行から特定の期間におけるこれらの ID のすべてのタイプのヒットのメッセージとカウントを再度取得します。最初のクエリについては、次のようになります。

SELECT entity, count(entity) as Count
from plugin_status_alerts
where entered BETWEEN now() - INTERVAL '14 days' AND now()
group by entity
order by count(entity) DESC
limit 10

これにより、次の結果が返されます。

"38792";3
"39416";2
"37796";2
"39145";2
"37713";2
"37360";2
"37724";2
"39152";2
"39937";2
"39667";2

次に、その結​​果セットを使用して、エンティティと status_code で並べ替える別のクエリを実行します。私はこのようなことを試しました:

SELECT status_code, entity, COUNT(status_code) statusCount
FROM plugin_status_alerts
where updated BETWEEN now() - INTERVAL '14 days' AND now() AND entity IN 
(SELECT id.entity, count(id.entity) as Count
from plugin_status_alerts id
where id.updated BETWEEN now() - INTERVAL '14 days' AND now()
group by id.entity
order by count(id.entity) DESC
limit 10
)
GROUP BY status_code, entity

しかし、私はエラーが発生します

ERROR: subquery has too many columns

これが私が進むべきルートなのか、それとも自己結合を試みる必要があるのか​​ 、どちらにしても、現在起こっていることを修正する方法がわからない.

4

2 に答える 2

1

JOINの代わりにa を使用しIN (subquery)ます。これは通常より高速であり、必要に応じてサブクエリから追加の値を使用できます ( あたりの合計カウントなどentity):

SELECT entity, status_code, count(*) AS status_ct
FROM  (
   SELECT entity  -- not adding count since you don't use it, but you could
   FROM   plugin_status_alerts
   WHERE  entered BETWEEN now() - interval '14 days' AND now()
   GROUP  BY entitiy
   ORDER  BY count(*) DESC, entitiy  -- as tie breaker to get stable result
   LIMIT  10
   ) sub
JOIN   plugin_status_alerts USING (entity)
WHERE  updated BETWEEN now() - interval '14 days' AND now()
GROUP  BY 1, 2;

ノート

  • 設計上将来のエントリがない場合は、次のように単純化できます。

    WHERE  entered > now() - interval '14 days'
    
  • entityサブクエリは、句とマージされる単一の列 ( ) のみを返すためUSING、列名は明確であり、ここではテーブル修飾は必要ありません。

  • LIMIT 10カウントで並べ替えた後は、あいまいになる可能性があります。複数の列が 10 列目に同点になる場合があります。に追加の項目ORDER BYがない場合、Postgres は任意の選択を返しますが、これは問題ない場合があります。ただし、クエリの結果は、基になるデータを変更することなく、呼び出し間で変わる可能性があります。通常、これは望ましくないため、リストに列または式を追加して、同点を解消する必要があります。

  • count(*)よりも少し速くcount(status_code)、同じことを行いstatus_codeます-nullにできない場合を除き、実際の行数の代わりに0この行の数として取得されます(count()nullを返すことはありません)。これは役に立たないか、積極的に間違っています。ここではどちらかを使用count(*)してください。

  • GROUP BY 1, 2は単なる構文上の省略形です。詳細:

于 2015-03-18T03:29:48.317 に答える
0

最初のクエリを 2 番目のクエリにプラグインしてin句で使用すると、1 つだけが必要な場合でも 2 つの列が返されますin。次のいずれかを行います。

SELECT status_code, entity, COUNT(status_code) statusCount
FROM plugin_status_alerts
where updated BETWEEN now() - INTERVAL '14 days' AND now() 
AND entity IN (
    SELECT id.entity
    from plugin_status_alerts id
    where id.updated BETWEEN now() - INTERVAL '14 days' AND now()
    group by id.entity
    order by count(id.entity) DESC
    limit 10
)
GROUP BY status_code, entity

または、最初のクエリを派生テーブルとして使用し、それと結合します。

于 2015-03-17T23:14:15.960 に答える