2016-03-20 8 views
0

Ich habe eine Sammlung von übergeordneten Elementen und jede hat eine unbestimmte Reihe von untergeordneten Elementen. Jedes untergeordnete Element als ein Attribut, das X oder NULL ist. (Entschuldigt für die ungeraden Boolesche Struktur, aber das ist, was ich habe, mit zu arbeiten.)Verwenden Sie SQL, um übergeordneten Datensatz FALSE anzuzeigen, wenn alle untergeordneten Werte Null sind

Parent Child Attribute 
------ ----- --------- 
    A  1  X 
    A  2  X 
    A  3  NULL 

    B  1  X 
    B  2  NULL 
    B  3  NULL 

    C  1  X 
    C  2  X 

    D  1  NULL 

    E  1  NULL 
    E  2  NULL 

Ich möchte Eltern Artikel als wahr oder falsch auf der Grundlage der untergeordneten Elemente identifizieren. Ein NULL Wert führt zu einer falschen Rückgabe für diesen übergeordneten Artikel. Hier sind die gewünschten Ergebnisse:

A  False 
    B  False 
    C  True 
    D  False 
    E  False 

Die ideale Lösung wäre auch ein Elternteil behandeln, die keine Kind Aufzeichnungen hat (Ergebnis ist False).

Ich kann dies mit temporären Tabellen tun. Diese Lösung ist ziemlich lang, und ich denke nicht, dass das Präsentieren einen Mehrwert für diesen Beitrag bedeuten würde.

Wie kann ich dies mit einer SQL-Abfrage ohne temporäre Tabellen tun?

Ich würde präsentieren "Dinge, die ich versucht habe", aber ich weiß nicht genug, wie man überhaupt anfängt.

+0

Was passiert, wenn ein Elternteil überhaupt keine Kinder hat? –

+0

Wie oben erwähnt, ist "Ergebnis ist falsch". – Smandoli

+0

Ah ja. Dann @GordonLinoff Lösung wird funktionieren. –

Antwort

2

Ich glaube nicht, dass dies nor entspricht. Sie möchten nur wissen, ob irgendwelche Werte NULL sind - oder äquivalent, wenn alle Werte 'X' sind. Verwenden Sie case und aggregation:

select parent, 
     (case when count(*) = count(attribute) then 'true' 
      else 'false' 
     end) 
from t 
group by parent; 

Um einen Elternteil ohne Kinder zu behandeln erfordert eine Liste von Eltern, getrennt von dieser Liste:

select p.parent, 
     (case when count(*) = count(t.attribute) and count(t.parent) > 0 then 'true' 
      else 'false' 
     end) 
from parents p left join 
    t 
    on p.parent = t.parent 
group by p.parent; 

Zur Erinnerung: count(*) zählt die Anzahl der Zeilen in dem Ergebnis einstellen. COUNT() mit einem Ausdruck (einschließlich einer Spalte) zählt die Anzahl der Nicht-NULL-Werte. Wenn diese identisch sind, gibt es keine Nicht-NULL-Werte.

+0

Das OP möchte auch den Fall ohne Kinder behandeln, also wird die 2. Lösung funktionieren. –

1

Sie können dies über Aggregate tun .., wenn keine Attribute, i die Spalte als leer gehalten haben ..

Zusammengefasst zuweisen wahr oder falsch zu jeder Zeile und erhalten min Wert

create table #test 
(
id int, 
name char(2) 
) 

insert into #test 

select 1,'x' 
union all 
select 1,null 
union all 
select 2,null 
union all 
select 3,'' 

with cte 
as 
(
select id,b.* 
from #test t1 
cross apply 
(
select case when name is null or name='' then 'False' Else 'True' end as 'chk' from #test t2 where t2.id=t1.id) b 
) 
select id,min(chk) 
from 
cte group by id 

Sie können entfernen sogar Quer anwenden:

with cte 
as 
(
select id,case when name is null or name='' then 'False' Else 'True' end as 'chk' 
from #test t1 
) 
select id,min(chk) 
from 
cte group by id 

Ausgang:

1 False 
2 False 
3 False 
+0

Das verwendet eine temporäre Tabelle als Teil einer gespeicherten Prozedur oder möglicherweise einer Ansicht. Wie gesagt, ich möchte in einer Abfrage damit umgehen. – Smandoli

+0

Ich habe nicht das Handle es in einem Abfrageteil.does bedeutet dies in einem einzigen Select – TheGameiswar

+0

Es bedeutet, eine Ad-hoc-Abfrage anstelle einer prozeduralen Ansatz verwenden. Siehe http://stackoverflow.com/a/22970/122139. Dies bedeutet nicht, dass nur ein SELECT verwendet wird - es ist möglich, Abfragen zu verschachteln oder UNION zu verwenden. Diese erlauben leicht mehrere SELECTS.Es * bedeutet * keine temporäre Tabelle zu verwenden. – Smandoli

Verwandte Themen