web-dev-qa-db-ja.com

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回ヒットしないようにします。

51
Stewart Johnson

Oracle:

nvl2によるグループ化(フィールド、「NOT NULL」、「NULL」)

23
trunkc

MySQLでは、次のようなことができます

SELECT 
    IF(ISNULL(processed_timestamp), 'NULL', 'NOT NULL') as myfield, 
    COUNT(*) 
FROM mytable 
GROUP BY myfield
43
Stefan Gehrig

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
39
Tomalak

以下を試してください、それはベンダー中立です:

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に不必要な負荷をかけます。このソリューションにはその問題はありません。

21
paxdiablo

Oracleの場合、次のことができます。

select decode(field,NULL,'NULL','NOT NULL'), count(*)
from table
group by decode(field,NULL,'NULL','NOT NULL');

他のDBでも同様のトリックが可能だと確信しています。

5
ADEpt

スチュワート、

たぶん、このソリューションを検討してください。 (また!)ベンダー非特定です。

SELECT count([processed_timestamp]) AS notnullrows, 
       count(*) - count([processed_timestamp]) AS nullrows 
FROM table

効率性に関しては、結果を1行に含めることで、2回のインデックスシーク/テーブルスキャンなどを回避します。結果に絶対に2行が必要な場合は、集合体を結合するため、セットを2回通過することが避けられない場合があります。

お役に立てれば

5
James Green

データベースにテーブル用の効率的なCOUNT(*)関数がある場合、どちらか小さい方をCOUNTして減算できます。

1
dkretz

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 
1
Refael

別の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
1
Tom

SQL Server(2012以降):

SELECT IIF(ISDATE(processed_timestamp) = 0, 'NULL', 'NON NULL'), COUNT(*)
FROM MyTable
GROUP BY ISDATE(processed_timestamp);
1
Jatin Sanghvi
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

編集:慎重に読んでいない、これは単一の行を返します。

[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時以降。

0
Unsliced

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

仕事をするべきです。

列にインデックスが付けられている場合、何らかの範囲スキャンが行われ、実際にテーブルを読み取らないようにすることができます。

0
EvilTeach

個人的には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

お役に立てれば

0
James Green