1

私は次のSYBASESQLに出くわしました。

-- Setup first
create table #t (id int, ts int)
go

insert into #t values (1, 2)
insert into #t values (1, 10)
insert into #t values (1, 20)
insert into #t values (1, 30)

insert into #t values (2, 5)
insert into #t values (2, 13) 
insert into #t values (2, 25)
go

declare @time int select @time=11
-- This is the SQL I am asking about
select * from (select * from #t where ts <= @time) t group by id having ts = max(ts)
go

このSQLの結果は次のとおりです。

 id          ts          
 ----------- ----------- 
           1          10 
           2           5 

これは、グループではなく行に適用されたHAVING条件のように見えます。このケースが説明されているSybase15.5のドキュメントがある場所を誰かに教えてもらえますか?私が見るのは「HAVINGはグループで動作する」だけです。私がドキュメントで見る最も近いものは次のとおりです:

持つ句には、選択リストにもgroupby句にも含まれない列または式を含めることができます。

(ここから引用)。

しかし、彼らはあなたがそれをしたときに何が起こるかを正確に説明していません。

4

3 に答える 3

1

Sybase は MS SQL Server....90 年代とコードを共有していたので行っていませんが、あなたがしていることについての私の解釈は次のとおりです。

最初に、リストは <= 11 にフィルタリングされます

id   ts
1    2
1    10
2    5

それ以外はすべて除外されます。

次に、TS = そのグループの Max(TS) である行にリストをフィルタリングします。

id   ts
1    10
2    5

10 はグループ 1 の Max(TS) であり、5 はグループ 2 の Max(TS) です。これらの 2 つの行が残ります。そうでなければ、どのような結果が期待できますか?

于 2013-03-19T19:11:16.857 に答える
1

私の理解: はい、基本的に HAVING は行を操作します。GROUP BY を省略することにより、グループ内の行ではなく、単一の「スーパーグループ」内のすべての結果行で動作します。最初にリンクされた Sybase doccoのセクション「How group by and having query with aggregates work」をお読みください:-

集計を使用したグループ化とクエリの仕組み

  • where句は、検索条件を満たさない行を除外します。その機能は、グループ化されたクエリでもグループ化されていないクエリでも同じです。
  • group by句は、残りの行をgroup by式の一意の値ごとに 1 つのグループにまとめます。group byを省略すると、テーブル全体に対して単一のグループが作成されます。
  • 選択リストで指定された集計関数は、各グループの集計値を計算します。スカラー集計の場合、テーブルの値は 1 つだけです。ベクトル集計は、個別のグループの値を計算します。
  • having句は、検索条件を満たさない結果からグループを除外します。having句は行のみをテストしますが、 group by句 の有無によって、グループを操作しているように見える場合があります。
    • クエリにgroup byが含まれている場合、havingは結果グループ行を除外します。これが、havingがグループに作用しているように見える理由です。
    • クエリにgroup byがない場合、 (単一グループ) テーブルから結果行除外します。これが、havingが行を操作しているように見える理由です (結果はwhere句の結果に似ています)。

次に、 「having、group by、および where 句がどのように相互作用するか」セクションに簡単な要約が表示されます。

having、group by、および where 節がどのように相互作用するか

クエリにhavinggroup by、およびwhere句を含めると、各句が行に影響を与える順序によって最終結果が決まります。

  • where句は、検索条件を満たさない行を除外します。
  • group by句は、残りの行をgroup by式の一意の値ごとに 1 つのグループにまとめます。
  • 選択リストで指定された集計関数は、各グループの集計値を計算します。
  • having句は、検索条件を満たさない行を最終結果から除外します。

@SQLGuruの説明はこれの実例です。

編集...

関連する点として、TSQL の「拡張列」を使用する非 ANSI 準拠のクエリの動作に驚きました。Sybase は、(i) WHERE 句の後で(ii)元のテーブルへの追加の結合を作成することによって拡張列を処理し、 (iii) WHERE 句は結合で使用されません。このようなクエリでは、予想よりも多くの行が返される可能性があり、HAVING 句ではこれらを除外するための追加条件が必要になります。

最初にリンクされたドキュメントのページの「Transact-SQL extensions to group by and having」の下にある例bc、およびdを参照してください。Sybase からpubs2サンプル データベースをインストールして、サンプルを試してみると便利です。

于 2013-04-11T10:40:55.480 に答える
1

ここのドキュメントを読むと、Sybase がhaving句に現れない句の列を使用するのgroup byは MySQL とは異なるようです。

彼らが与える例には、次の説明があります。

Transact-SQL の拡張列である price (選択リストにありますが、集計ではなく、group by 句にはありません) を使用すると、標準の group by 句では 1 行ごとに 1 つの行が生成されますが、すべての適格な行が各適格なグループに表示されます。グループ。group by は、各グループの各行に表示されるグループごとの平均価格を計算するベクトル集計に引き続き影響します (これらは、たとえば a で計算された値と同じです)。

したがって、ts = max(ts)本質的にこれを行います:

select *
from (select t.*,
             max(ts) over (partition by id) as maxts
      from #t
      where ts <= @time
     ) t
where ts = maxts

where句がmax()計算に使用されすべての行が返されるため、サブクエリは重要です。

私は、この振る舞いがかなり紛らわしく、非標準的だと思います。私はそれをより典型的な構造に置き換えます。これらはほぼ同じレベルの複雑さであり、より多くの聴衆にとってより明確に見えます.

于 2013-03-19T20:39:21.167 に答える