Frage

Ich habe eine Tabelle, die eine Spalte processed_timestamp hat - wenn ein Datensatz dann verarbeitet wurde das Feld der Datetime enthält es verarbeitet wurde, andernfalls 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 recht groß, so Effizienz ist wichtig. Ich konnte nur zwei Abfragen ausführen jeweils insgesamt separat zu berechnen, aber ich mag zweimal auf den Tisch schlagen, um zu vermeiden, wenn ich es vermeiden kann.

War es hilfreich?

Lösung

Oracle:

Gruppe von NVL2 (Feld, 'NOT NULL', 'NULL')

Andere Tipps

In MySQL Sie etwas tun könnte, wie

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

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

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

Versuchen Sie, die folgenden, es ist herstellerneutrale:

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

unseren lokalen DB2-Guru Blick auf diesem Nachdem er stimmt zu: keiner der bisher vorgestellten Lösungen (einschließlich diesem) einem vollständigen Tabellenscan vermeiden kann (der Tabelle, wenn Zeitstempel nicht indiziert ist, oder die indexotherwise). Sie alle scannen jeden Datensatz in der Tabelle genau einmal.

All CASE / IF / NVL2 () -Lösungen machen eine Null-zu-String-Konvertierung für jede Zeile, auf dem DBMS unnötige Belastung einzuführen. Diese Lösung ist nicht das Problem hat.

Wenn es Orakel dann können Sie 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 nach ähnlichem Trick ermöglichen.

Stewart,

Vielleicht diese Lösung in Betracht ziehen. Es ist (auch!) Anbieter unspezifisch.

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

Wie für Effizienz, dies vermeidet 2x Index sucht / Table Scans / was auch immer durch die Ergebnisse auf einer Zeile darunter. Wenn Sie unbedingt benötigen zwei Zeilen in der Folge zwei Durchgänge über den Satz kann wegen unioning Aggregate nicht zu vermeiden sein.

Hope, das hilft

Eine andere MySQL-Methode ist die CASE Operator , die zu 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

Wenn Ihre Datenbank eine effiziente COUNT (*) Funktion für eine Tabelle hat, könnte man COUNT je nachdem, was ist die kleinere Zahl und subtrahieren.

SQL Server (ab 2012):

SELECT IIF(ISDATE(processed_timestamp) = 0, 'NULL', 'NON NULL'), COUNT(*)
FROM MyTable
GROUP BY ISDATE(processed_timestamp);

Ich persönlich mag Pax-Lösung, aber wenn Sie unbedingt benötigen nur eine Zeile zurück (wie ich vor kurzem hatte), in MS SQL Server 2005/2008 können Sie „Stapel“, die beiden Abfragen mit einem CTE

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

Hope, das hilft

[T-SQL]:

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

Und Sie können in die Case-Anweisung hinzufügen, was auch immer andere Werte, die Sie möchten, dass eine Partition bilden, z.B. heute, gestern, zwischen Mittag und 14.00 Uhr, nach 18.00 Uhr an einem Donnerstag.

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 hat, gibt diese ein eine einzelne Zeile

.

In Oracle

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

count (*) gibt die Anzahl aller Zeilen

count (column_name) gibt die Anzahl der Zeilen, die nicht NULL sind, so

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

sollte die Arbeit tun.

Wenn die Spalte indiziert ist, können Sie mit irgendeiner Art von Bereichsscan am Ende und vermeiden tatsächlich die Tabelle zu lesen.

Eine weitere Möglichkeit, 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 
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top