NULLおよびNOT NULLでグループ化されたレコードを返すにはどうすればよいですか?
質問
processed_timestamp
列を持つテーブルがあります-レコードが処理された場合、そのフィールドには処理された日時が含まれ、そうでない場合はnullです。
2行を返すクエリを作成します:
NULL xx -- count of records with null timestamps
NOT NULL yy -- count of records with non-null timestamps
それは可能ですか?
更新:テーブルは非常に大きいため、効率が重要です。 2つのクエリを実行して各合計を個別に計算することもできますが、回避できる場合はテーブルに2回ヒットしないようにします。
解決
Oracle:
nvl2によるグループ化(フィールド、「NOT NULL」、「NULL」)
他のヒント
MySQLでは、次のようなことができます
SELECT
IF(ISNULL(processed_timestamp), 'NULL', 'NOT NULL') as myfield,
COUNT(*)
FROM mytable
GROUP BY myfield
T-SQL(MS SQL Server)では、これは機能します:
SELECT
CASE WHEN Field IS NULL THEN 'NULL' ELSE 'NOT NULL' END FieldContent,
COUNT(*) FieldCount
FROM
TheTable
GROUP BY
CASE WHEN Field IS NULL THEN 'NULL' ELSE 'NOT NULL' END
次を試してください、ベンダー中立です:
select
'null ' as type,
count(*) as quant
from tbl
where tmstmp is null
union all
select
'not null' as type,
count(*) as quant
from tbl
where tmstmp is not null
ローカルDB2の第一人者にこれを見てもらうと、彼は同意します。これまでに提示されたソリューション(これを含む)は、(タイムスタンプがインデックス付けされていない場合はテーブルの、またはその他の場合は)テーブル全体のスキャンを回避できません。これらはすべて、テーブル内のすべてのレコードを1回だけスキャンします。
すべてのCASE / IF / NVL2()ソリューションは、行ごとにNULLから文字列への変換を行い、DBMSに不必要な負荷をかけます。このソリューションにはその問題はありません。
オラクルの場合、次のことができます:
select decode(field,NULL,'NULL','NOT NULL'), count(*)
from table
group by decode(field,NULL,'NULL','NOT NULL');
他のデータベースでも同様のトリックが可能だと確信しています。
Stewart、
このソリューションを検討してください。 (また!)ベンダー非特定です。
SELECT count([processed_timestamp]) AS notnullrows,
count(*) - count([processed_timestamp]) AS nullrows
FROM table
効率については、1行に結果を含めることにより、2回のインデックスシーク/テーブルスキャンなどを回避します。結果に絶対に2行が必要な場合は、集合体を結合するため、セットを2回通過することが避けられない場合があります。
これが役立つことを願って
別のMySQLメソッドは、を使用することです CASE
演算子。 IF()
:
SELECT CASE WHEN processed_timestamp IS NULL THEN 'NULL'
ELSE 'NOT NULL' END AS a,
COUNT(*) AS n
FROM logs
GROUP BY a
データベースにテーブル用の効率的なCOUNT(*)関数がある場合、小さい方をCOUNTして減算できます。
SQL Server(2012以降):
SELECT IIF(ISDATE(processed_timestamp) = 0, 'NULL', 'NON NULL'), COUNT(*)
FROM MyTable
GROUP BY ISDATE(processed_timestamp);
個人的にはPaxのソリューションが好きですが、(最近持っていたように)返される行が1つだけ必要な場合、MS SQL Server 2005/2008では、「スタック」できます。 CTEを使用した2つのクエリ
with NullRows (countOf)
AS
(
SELECT count(*)
FORM table
WHERE [processed_timestamp] IS NOT NULL
)
SELECT count(*) AS nulls, countOf
FROM table, NullRows
WHERE [processed_timestamp] IS NULL
GROUP BY countOf
これが役立つことを願って
[T-SQL]:
select [case], count(*) tally
from (
select
case when [processed_timestamp] is null then 'null'
else 'not null'
end [case]
from myTable
) a
そして、あなたはパーティションを形成したい他のどんな値でも、caseステートメントに追加できます。今日、昨日、正午から午後2時まで、木曜日の午後6時以降。
Select Sum(Case When processed_timestamp IS NULL
Then 1
Else 0
End) not_processed_count,
Sum(Case When processed_timestamp Is Not NULL
Then 1
Else 0
End) processed_count,
Count(1) total
From table
編集:注意深く読みませんでした。これは単一の行を返します。
Oracleで
SELECT COUNT(*), COUNT(TIME_STAMP_COLUMN)
FROM TABLE;
count(*)はすべての行のカウントを返します
count(column_name)は、NULLではない行の数を返すため、
SELECT COUNT(*) - COUNT(TIME_STAMP_COLUMN) NUL_COUNT,
COUNT(TIME_STAMP_COLUMN) NON_NUL_COUNT
FROM TABLE
仕事をする必要があります。
列にインデックスが付けられている場合、何らかの範囲スキャンが行われ、テーブルを実際に読み取らないようにする可能性があります。
T-sqlの別の方法(sql-server)
select count(case when t.timestamps is null
then 1
else null end) NULLROWS,
count(case when t.timestamps is not null
then 1
else null end) NOTNULLROWS
from myTable t