2016-05-30 3 views
1

Ich arbeite mit einer Datentabelle, die einige Zeilen als eine Art Sicherung kopiert hat. Ich versuche, Daten herauszufiltern, die kopiert wurden, aber ich habe Probleme, weil ich nach einem Spaltenpaar filtern muss. Jede Zeile hat einen Namen und ein Datum, ein Flag für wenn es eine Kopie ist oder ein paar andere Dinge (hat mehr als nur zwei Werte, aber das sind die, an denen ich interessiert bin) und einige andere Informationen. Ich versuche, alle Zeilen zu erhalten, die als Backups nicht angezeigt werden, so zum Beispiel:C# SQL-Filter für ein Wertepaar?

ABC 1/1/2001 dataSet ...  |  ABC 1/1/2001 backupSet ... 
DEF 2/2/2002 dataSet ...  |  DEF 2/2/2002 backupSet ... 
GHI 3/3/2003 dataSet ...  |  ABC 4/4/2004 backupSet ... 
ABC 4/4/2004 dataSet ...  |  
DEF 5/5/2005 dataSet ...  |  
ABC 6/6/2006 dataSet ...  |  

ergäbe in:

GHI 3/3/2003 dataSet ... 
DEF 5/5/2005 dataSet ... 
ABC 6/6/2006 dataSet ... 

ich auf einer Spalte filtern kann, aber ich weiß nicht wissen wie beides gleichzeitig geht.

var result = from a in db.table 
where a.type == "dataSet" 
let backupData = (from b in db.table where b.type == "backupSet" select b.name) 
where !backupData.Contains(a.type) 
select new DataObject 
{ 
    ... 
}; 

Ist so weit wie ich habe.

Ich versuche auch, es zu nur einer Abfrage zu behalten, da die Ergebnismenge möglicherweise ziemlich groß sein könnte, also wollte ich nicht einfach ein Paar Sammlungen im Speicher erstellen und dann versuchen, sie herauszufiltern. Ist das möglich? Noch etwas unerfahren bei SQL, wird jede Hilfe geschätzt.

Antwort

1

Sie können entweder Any verwenden (Mit !):

var result = 
    from a in db.table 
    where a.type == "dataSet" 
     && !db.table.Any(b => b.type == "backupSet" 
      && b.name == a.name && b.date == a.date) 
    select new DataObject 
    { 
     ... 
    }; 

oder (sucht ein wenig komplizierter, aber im Allgemeinen sehr effizient) antijoin (implementiert als left outer join mit null rechts):

var result = 
    from a in db.table.Where(x => x.type == "dataSet") 
    join b in db.table.Where(x => x.type == "backupSet") 
     on new { a.name, a.date } equals new { b.name, b.date } into bGroup 
    from b in bGroup.DefaultIfEmpty() 
    where b == null 
    select new DataObject 
    { 
     ... 
    }; 
+0

Das funktionierte, danke. – user1267983

0

Je nachdem, was Sie zu tun versuchen (und was Sie tun können), Sie group by verwenden möchten, name unter der Annahme, ist der Schlüssel BACKUPSET und dataSet miteinander zu verknüpfen:

var result = db.Table 
    .GroupBy(x => new { x.name, x.type }) // Composite key 
    .Select(g => new { 
     Name = g.Key.name, // ABC, DEF, etc 
     Type = g.Key.type, // "backupSet", "dataSet" 
     LastRecord = g.OrderByDescending(x => x.date).FirstOrDefault() // Last record for either backupSet or dataSet 
    }) 
    .ToList() // Materialize... query can be very complex 
    .GroupBy(x => x.Name) 
    .Select(g => new { 
     Name = g.Key, 
     LastBackupSet = g.First(x => x.Type == "backupSet").LastRecord, 
     LastDataSet = g.First(x => x.Type == "dataSet").LastRecord 
    }) 
    .ToList(); 

Vorsicht aber, g.First im letzten Ausdruck kann werfen Sequenz enthält keine Elemente und .LastRecordObjektverweis nicht auf eine Instanz eines Objekts festgelegt werfen kann

Verwandte Themen