Doppelte Datensätze zusammenführen

FanClub

Mitglied
Hi,

ich habe ein wohl eher triviales Problem, finde aber keinen Ansatz zum Suchen und zum entwickeln.

Ich habe eine Liste von DTO's. In dieser Liste kommen identische Datensätze vor, sie unterscheiden sich lediglich in einem Feld. Bei der Anzeige dieser Datensätze müssen diese aber aneinander gehängt sein.
Beispiel:

Name|Alter|Sport
Mike|25|Fußball
Mike|25|Tennis
Klaus|30|Fußball
Klaus|30|Dart

So wird es auch angezeigt, sind ja vier Elemente in meiner Liste.
Ich würde es aber gerne so haben, dass es nur noch zwei Elemente in meiner Liste sind und das Attribut Sport ebenfalls zu einer Liste wird, die ich anschließend ausgebe. Denke ich da zu verkrampft?

So sollte es aussehen:
Name|Alter|Sport
Mike|25|Fußball Tennis
Klaus|30|Fußball Dart

Wie realisiere ich das am einfachsten?

gruß
 
Ich glaube, es gibt dafür keinen SQL-Standardweg. Sprich, das SQL muss für das eingesetzte DBMS passen. Welches nutzt Du denn?

Z.B. bei MySQL kannst Du die Aggregatfunktion
Code:
GROUP_CONCAT()
benutzen. Das Statement sähe dann so aus:
SQL:
SELECT Name, Alter, GROUP_CONCAT(Sport ORDER BY Sport ASC SEPARATOR ',')
  FROM Sportler
  GROUP BY (Name, Alter);
Wie Du siehst, ist "Alter" ein schlechter Spaltenname, weil es ein reserviertes Wort in SQL ist!
 
Und wenn wir davon ausgehen, dass ich die Daten so aus der Datenbank schon gelesen habe und jetzt eine Liste mit den DTO's habe.

Beispiel: List(dto1(mike, 25, fußball), dto2(mike,25, tennis), dto3(klaus, 30, fußball), dto4(klaus, 30, dart)

Bei der Ausgabe komme ich hier natürlich etwas ins schwimmen.
Mir wäre es lieber wenn ich aus dieser Liste folgendes machen könnte:

List(dto1(mike, 25, List(Fußball, Tennis)), dto2(klaus, 30,List(Fußball, Dart))).

So könnte ich dann bei der ausgabe folgendes machen:
Java:
 <c:forEach var="curr1" items="${result.Liste1}">
--> hier kommt dann der Name (Mike) <--
<c:forEach var="curr2" items="${result.Liste1.Liste2}">
--> hier kommen dann Fußball, Tennis <--
</c:forEach>
</c:forEach>
 
Mir wäre es lieber wenn ich aus dieser Liste folgendes machen könnte:

List(dto1(mike, 25, List(Fußball, Tennis)), dto2(klaus, 30,List(Fußball, Dart))).

Was hindert dich denn daran, es so zu machen, wenn du es so haben möchtest?
Iterier über deine Liste und lege eine neue an, in der du jedes Element einträgst. Wenn es schon vorhanden ist, ergänzt du nur die Sportart.
 
Genau so mache ich es auch aber das kommt hier recht umständlich vor.

Während ich das ResultRet in ein dto fülle, was ich wiederrum in eine Liste eintrage, frage ich nun ab, ob der vorherige Eintrag dem jetzigen entspricht. (Das Resultset ist so sortiert, dass die Daten wie "Mike" beispielsweiße nicht durcheinander sind - anhand einer ID - (Mike hat als beispiel die nummer 552)).
Wenn das der Fall ist, erweitere ich die Liste der Sportart um den aktuellen Wert und überschreibe das vorher eingetragene DTO.

Das kommt mir alles sehr umständlich vor. 🙂
 
Also das überschreiben in der Liste wirst du dir höchstwahrscheinlich sparen können, in der Liste stehen nur Referenzen auf deine DTOs.
 
Bei mir sieht es aktuell so aus...

Java:
List listData = new ArrayList();
List abListe = new ArrayList();
...
resultset wird via while in eine Liste geschrieben, dabei werden DTOs erzeugt
person_id = resultset.getString("PERSON_ID")
...
if(listData.size()!=0){
  PersonDTO persondto=(PersonDTO)listData.get(listData.size()-1);
  if(person_id.equals(persondto.getPerson_id())){
    abListe = persondto.getSportartListe();
    abListe.add(resultSet2.getString("SPORTART"));
    persondto.setSportartListe(abListe);
    listData.set(listData.size()-1, persondto);
    continue;
  }else{
   abListe.add(resultSet2.getString("SPORTART"));
  }
}else{
  abListe.add(resultSet2.getString("SPORTART"));
}
 
Benutz generics bei listen, das hilft der Lesbarkeit enorm. Was ich ausdrücken wollte ist folgendes:
Java:
import java.util.ArrayList;
import java.util.List;

public class DTO
{
	String name;
	
	public DTO(String n)
	{
		name = n;
	}
	
	public void setName(String n)
	{
		name = n;
	}
	
	public String getName()
	{
		return name;
	}
	
	public static void main(String args[])
	{
		List<DTO> liste = new ArrayList<DTO>();
		DTO d1 = new DTO("Hallo");
		liste.add(d1);
		d1.setName("Hallo Welt");
		//Das DTO d1 braucht nicht erneut in die Liste geschrieben zu werden
		//weil d1 und das DTO in der Liste ein und das selbe Objekt sind.
		for (DTO d : liste)
		{
			System.out.println(d.getName());
		}
	}
}
 
Hi,

danke für deine Antwort aber so richtig kann ich das noch nicht nachvollziehen.

Wenn ich eine Liste mit DTOs habe -> List(d1,d2,d3,d4,d5) dann kann ich auf jedes einzelne seperat zugreifen. So weit so gut. Ich aber habe so eine Liste -> List(DTO,DTO,DTO,DTO,DTO).

So wie ich das bei dir gelesen habe, weiß ich doch nicht, welches DTO da mit den neuen Werten beschrieben werden soll?! Oder reden wir gerade aneinander vorbei? 🙂
 
So wie ich dich verstanden habe hast du eine List(DTO,DTO,DTO,DTO,DTO). Aus der suchst du dir ein bestimmtes DTO raus, z.B das 4. Dann änderst du irgendwas an deinem DTO und schreibst es mit List.set wieder an die 4. Stelle. Das set kannst du dir sparen.
 
Und die verschachtelten for-Eachs in Deinem JSP-Code sind so auch noch nicht ganz richtig. Es müsste eher so aussehen
[XML]
<c:forEach var="curr1" items="${result.Liste1}">
--> hier kommt dann der Name (Mike) <--
<!-- Du musst die Laufvariable "curr1" der äußeren Schleife benutzen -->
<c:forEach var="curr2" items="${curr1.sportArtListe}">
--> hier kommen dann Fußball, Tennis <--
</c:forEach>
</c:forEach>
[/XML]
 
Für die Datentransformation: Ich würde einfach aus deinem [c]PersonDTO[/c] eine [c]Map<Person, List<String>>[/c] machen. Dazu musst du lediglich eine Klasse [c]Person[/c] schreiben - dabei [c]equals()[/c] und [c]hashCode()[/c] sinnvoll überschreiben! Dann kannst du das ganz einfach prozessieren:
Java:
private Map<Person, List<String>>  persons;

public void foo() {
    // ...
    for (PersonDTO p : listData) {
        Person person = new Person(p.getFoo(), p.getBar(), p.getName());
        insertPerson(person, p.getSportart());
    }
    // ...
}

protected void insert(Person person, String sportart) {
    if (!persons.containsKey(person)) {
        persons.put(person, new ArrayList());
    }
    persons.get(person).add(sportart);
}
 

Neue Themen


Zurück
Oben