it-swarm.com.de

Wie gebe ich meine Datensätze zurück, gruppiert nach NULL und NICHT NULL?

Ich habe eine Tabelle mit einer processed_timestamp-Spalte. Wenn ein Datensatz verarbeitet wurde, enthält dieses Feld die verarbeitete Datumszeit, andernfalls ist es null.

Ich möchte eine Abfrage schreiben, die zwei Zeilen zurückgibt:

NULL        xx -- count of records with null timestamps
NOT NULL    yy -- count of records with non-null timestamps

Ist das möglich?

Update: Der Tisch ist ziemlich groß, daher ist Effizienz wichtig. Ich könnte einfach zwei Abfragen ausführen, um jede Summe separat zu berechnen, aber ich möchte vermeiden, die Tabelle zweimal zu schlagen, wenn ich es vermeiden kann.

48
Stewart Johnson

Orakel:

gruppieren nach nvl2 (Feld, 'NOT NULL', 'NULL')

23
trunkc

In MySQL könnten Sie so etwas tun

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

In T-SQL (MS SQL Server) funktioniert das:

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

Versuchen Sie Folgendes, es ist herstellerunabhängig:

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

Nachdem sich unser lokaler DB2-Guru dies angesehen hat, stimmt er zu: Keine der bisher vorgestellten Lösungen (einschließlich dieser) kann eine vollständige Tabellensuche (der Tabelle, wenn der Zeitstempel nicht indiziert ist) oder des Index ansonsten verhindern. Sie alle scannen jeden Datensatz in der Tabelle genau einmal. 

Alle CASE/IF/NVL2 () -Lösungen führen für jede Zeile eine Null-zu-String-Konvertierung durch, wodurch das DBMS unnötig belastet wird. Diese Lösung hat dieses Problem nicht.

21
paxdiablo

Wenn es Oracle ist, können Sie Folgendes tun:

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

Ich bin sicher, dass andere DBs einen ähnlichen Trick zulassen.

5
ADEpt

Stewart,

Vielleicht überlegen Sie sich diese Lösung. Es ist (auch!) Herstellerunabhängig.

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

In Bezug auf die Effizienz werden 2x Indexsuchen/Tabellenscans/was auch immer vermieden, indem die Ergebnisse in eine Zeile aufgenommen werden. Wenn Sie unbedingt zwei Zeilen im Ergebnis benötigen, können zwei Durchgänge über dem Satz aufgrund von Vereinigungsaggregaten unvermeidbar sein.

Hoffe das hilft

5
James Green

Wenn Ihre Datenbank über eine effiziente COUNT (*) - Funktion für eine Tabelle verfügt, können Sie COUNT, je nachdem, welche Zahl kleiner ist, abziehen.

1
dkretz

Eine andere MySQL-Methode ist die Verwendung des CASE-Operators , der auf mehr Alternativen als IF() verallgemeinert werden kann:

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 (ab 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

Edit: nicht sorgfältig gelesen, diese Zeile gibt eine einzelne Zeile zurück.

[T-SQL]: 

select [case], count(*) tally
from (
  select 
  case when [processed_timestamp] is null then 'null'
  else 'not null'
  end [case]
  from myTable
) a 

Sie können der Case-Anweisung auch beliebige andere Werte hinzufügen, die Sie als Partition definieren möchten, z. heute, gestern, zwischen 12 und 14 uhr, donnerstags um 18 uhr. 

0
Unsliced

In Oracle

SELECT COUNT(*), COUNT(TIME_STAMP_COLUMN)
FROM TABLE;

count (*) gibt die Anzahl aller Zeilen zurück

count (Spaltenname) gibt die Anzahl der Zeilen zurück, die nicht NULL sind

SELECT COUNT(*) - COUNT(TIME_STAMP_COLUMN) NUL_COUNT,
                  COUNT(TIME_STAMP_COLUMN) NON_NUL_COUNT
FROM TABLE

sollte die Arbeit machen.

Wenn die Spalte indiziert ist, kann es zu einer Art Bereichsabtastung kommen, die das Lesen der Tabelle verhindert.

0
EvilTeach

Ein anderer Weg in 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 
0
Refael

Ich persönlich mag die Lösung von Pax, aber wenn Sie unbedingt nur eine zurückgegebene Zeile benötigen (wie kürzlich), können Sie in MS SQL Server 2005/2008 die beiden Abfragen mithilfe eines CTE "stapeln"

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

Hoffe das hilft

0
James Green