Ich habe eine Tabelle mit 2 Spalten in der Datenbank fls2, die Sqlite ist;

name        |    sha256
------------|------------------
ab/ac/ad    |    12345
ab/ad/af    |    12345
zx/ad/af    |    12345

Ich möchte Namen finden, bei denen 'Name wie' ab% 'und' Name nicht wie 'ab%' für einen bestimmten sha256 zutreffen. Im obigen Fall teilen sich die 3 Zeilen einen sha256 von '12345', und ich möchte dies als Unterdatensatz betrachten. Wenn in diesem Datensatz sowohl 'Name wie' ab% 'als auch' Name nicht wie 'ab%' wahr sind (natürlich für 2 oder mehr verschiedene Zeilen), möchte ich, dass alle Zeilen zurückgegeben werden.

Ich suche nach Fällen, in denen eine identische Datei (gekennzeichnet durch sha256) in zwei verschiedenen Verzeichnissen der obersten Ebene vorhanden ist.

Ich weiß, wie man das in Perl macht, nachdem ich die Daten abgerufen habe, aber im Idealfall wäre es weitaus besser, wenn ich das in der Datenbank machen könnte. Ich habe es versucht

select name 
from 
    fls2 
where 
    sha256 = (select sha256 from fls2 where name like 'ab%') 
and 
    name not like 'ab%';

Aber es werden keine Zeilen zurückgegeben (und ich weiß, dass es mindestens einige gibt, weil ich sie manuell gefunden habe).

0
Pete 23 Feb. 2020 im 02:40

3 Antworten

Beste Antwort

Wenn in diesem Datensatz sowohl 'Name wie' ab% 'als auch' Name nicht wie 'ab%' wahr sind (natürlich für 2 oder mehr verschiedene Zeilen), möchte ich, dass alle Zeilen zurückgegeben werden.

Sie können Fensterfunktionen verwenden:

select name, sha256
from (
    select 
        f.*,
        max(case when name like 'ab%' then 1 end) over(partition by sha256) max_ab,
        max(case when name not like 'ab%' then 1 end) over(partition by sha256) max_not_ab
    from fls2 f
) t
where max_ab = 1 and max_not_ab = 1

In der Unterabfrage prüft das Fenster max(), ob ein Datensatz mit demselben sha256 und einem Namen vorhanden ist, der mit 'ab%' beginnt (bzw. nicht startet). Anschließend filtert die äußere Abfrage nach Datensätzen, die beide Bedingungen erfüllen.

0
GMB 23 Feb. 2020 im 08:51

Verwenden Sie EXISTS:

select * from fls2 f
where
  exists (select 1 from fls2 where sha256 = f.sha256 and name like 'ab%')
  and
  exists (select 1 from fls2 where sha256 = f.sha256 and name not like 'ab%')

Siehe die Demo.
Oder mit der Fensterfunktion sum():

select f.name, f.sha256
from (
  select *, 
    sum(name like 'ab%') over (partition by sha256) sum1,
    sum(name not like 'ab%') over (partition by sha256) sum2
  from fls2
) f
where f.sum1 > 0 and f.sum2 > 0

Siehe die Demo.
Ergebnisse:

| name     | sha256 |
| -------- | ------ |
| ab/ac/ad | 12345  |
| ab/ad/af | 12345  |
| zx/ad/af | 12345  |
1
forpas 23 Feb. 2020 im 08:48

Verwenden Sie Aggregation und having:

select sha226, group_concat(name) as names
from t
group by sha226
having sum(case when name like 'ab%' then 1 else 0 end) > 0 and
       sum(case when name not like 'ab%' then 1 else 0 end) > 0;

Dadurch werden alle Namen in einer Liste in dieselbe Zeile eingefügt.

1
Gordon Linoff 22 Feb. 2020 im 23:47