Tabellen Joinen

mrmoos

Grünschnabel
Hallo,
ich bräuchte ganz allgemeine Anweisungen wie ich mit folgenedem Problem umgehe:
Ich soll zwei Tabellen(bzw. Relationen) miteinander Joinen und nur bestimmte Attribute(Spalten) anzeigen.
Die Tabellen stehen in einem Ordner im CSV-Format zur verfügung.
Das soll jetzt irgendwie mit Java geschehen und am Ende eine .exe ergeben. Was genau brauche ich dazu?
J2EE und JDBC? Soweit ich weis ist J2EE der Nachfolger vom JDK1.4!? JDBC ist irgendwie für Datenbanken.
Muss ich für meine Aufgabe überhaupt eine Datenbank aufbauen, dann bräuchte ich wahrscheinlich auch MySQL!?
Vieleicht kann mir jemand sagen welche tools und packete ich dazu brauche und wie ich solche Relationen in Java darstelle( Relation=Instanz einer Klasse oder Records= Instanz einer Klasse)?
Gibt es einen Link bzw. Referenz wo ich das nachlesen kann?

Danke und Gruß,
Mr.Moos
 
Hallo,

J2EE ist nicht der Nachfolger von JDK 1.4, das wäre eher JDK 5.0 und das neuste ist jetzt 6.0.
Grob gesagt ist J2EE für verteilte Anwendungen und Servlets/JSP. Du brauchst das normale JDK, welches es bei Sun zum download gibt.
Ne Datenbank brauchst du sicher, es muss nicht unbedingt MySQL sein, ist aber weit verbreitet und kostenlos. Den JDBC-Connector findest du auch auf dieser Seite.
Generell zu Java kann ich "Java ist auch eine Insel" empfehlen. Da findest du, denke ich mal, alles was du brauchst.

MFG
zEriX
 
Hi mrmoos
Schau dir mal derby an (Ist eine relationale DB für Java). Nun kannst du die CSV Dateien einlesen, den Datentyp der Felder ausfindig machen und dafür in der DB eine Tabelle erstellen und die Daten einfügen. Danach kannst du normal mit SQL arbeiten.

Gruss
jeipack
 
Hallo,

entweder baust du dir eine eigene Join Logik:
Java:
/**
 * 
 */
package de.tutorials;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;

/**
 * @author Tom
 */
public class InMemoryJoinExample {
  /**
   * @param args
   */
  public static void main(String[] args) {

    Table table1 = new Table("table1");
    table1.loadFromCSVFile(new File("c:/table1.csv"));

    Table table2 = new Table("table2");
    table2.loadFromCSVFile(new File("c:/table2.csv"));

    Table result = table1.join(table2).on(new IPredicate<Pair<DataRow>>() {
      public boolean evaluate(Pair<DataRow> argument) {
        return argument.left.get("COLUMN1").equals(argument.rigth.get("COLUMN1"));
      }
    }).toTable("joinedTable");
    System.out.println(result);
  }

  static class Table implements Iterable<DataRow> {

    final static String DEFAULT_SEPARATOR = ";";

    String name;
    Set<Column> columns = new LinkedHashSet<Column>();
    List<DataRow> dataRows = new ArrayList<DataRow>();
    Map<String, Column> columnNameToColumnMap = new HashMap<String, Column>();


    public Table(String name) {
      this.name = name;
    }


    /**
     * @return the name
     */
    public String getName() {
      return name;
    }


    public JoinOperation join(Table table) {
      return new JoinOperation(this, table);
    }


    public void loadFromCSVFile(File file) {
      try {
        Scanner scanner = new Scanner(file);

        buildTableColumnNamesFrom(scanner.nextLine());

        while (scanner.hasNextLine()) {
          addAsDataRow(scanner.nextLine());
        }
        scanner.close();
      } catch (FileNotFoundException e) {
        e.printStackTrace();
      }
    }


    private void addAsDataRow(String nextLine) {
      DataRow dataRow = new DataRow(this);
      int position = 0;
      for (String data : nextLine.split(DEFAULT_SEPARATOR)) {
        dataRow.set(position++, data);
      }
      getDataRows().add(dataRow);
    }


    private void buildTableColumnNamesFrom(String tableHeader) {
      int position = 0;
      for (String columnName : tableHeader.split(DEFAULT_SEPARATOR)) {
        addColumn(new Column(columnName, position++, String.class, this));

      }
    }


    private void addColumn(Column column) {
      getColumns().add(column);
      columnNameToColumnMap.put(column.getName(), column);
    }


    /**
     * @param name the name to set
     */
    public void setName(String name) {
      this.name = name;
    }


    /**
     * @return the columns
     */
    public Set<Column> getColumns() {
      return columns;
    }


    /**
     * @param columns the columns to set
     */
    public void setColumns(Set<Column> columns) {
      this.columns = columns;
      columnNameToColumnMap.clear();
      for (Column column : columns) {
        columnNameToColumnMap.put(column.getName(), column);
      }
    }


    /**
     * @return the dataRows
     */
    public List<DataRow> getDataRows() {
      return dataRows;
    }


    /**
     * @param dataRows the dataRows to set
     */
    public void setDataRows(List<DataRow> dataRows) {
      this.dataRows = dataRows;
    }


    public Iterator<DataRow> iterator() {
      return getDataRows().iterator();
    }


    public int getIndexForColumn(String columnName) {
      return columnNameToColumnMap.get(columnName).getIndex();
    }


    public String toString() {
      StringBuilder stringBuilder = new StringBuilder();

      for (Column column : getColumns()) {
        stringBuilder.append(column.getName()).append(", ");
      }
      stringBuilder.append("\n");

      for (DataRow dataRow : this) {
        for (int i = 0; i < dataRow.getRowData().length; i++) {
          stringBuilder.append(dataRow.getRowData()[i]).append(", ");
        }
        stringBuilder.append("\n");
      }

      return stringBuilder.toString();
    }
  }

  static class Column {
    String name;
    Class<?> type;
    int index;
    Table table;


    public Column(String name, int index, Class<?> type, Table table) {
      this.name = name;
      this.index = index;
      this.type = type;
      this.table = table;
    }


    /**
     * @return the name
     */
    public String getName() {
      return name;
    }


    /**
     * @param name the name to set
     */
    public void setName(String name) {
      this.name = name;
    }


    /**
     * @return the type
     */
    public Class<?> getType() {
      return type;
    }


    /**
     * @param type the type to set
     */
    public void setType(Class<?> type) {
      this.type = type;
    }


    /**
     * @return the index
     */
    public int getIndex() {
      return index;
    }


    /**
     * @param index the index to set
     */
    public void setIndex(int index) {
      this.index = index;
    }


    @Override
    public String toString() {
      return this.name + " " + this.type + " " + this.index;
    }


    public String getQualifiedName() {
      return this.table.getName() + "." + this.name;
    }
  }

  static class DataRow {
    Table table;
    Object[] rowData;


    public DataRow(Table table) {
      this.table = table;
      this.rowData = new Object[table.getColumns().size()];
    }


    public void set(int position, Object data) {
      this.rowData[position] = data;
    }


    public void set(String columnName, Object data) {
      set(getTable().getIndexForColumn(columnName), data);
    }


    /**
     * @return the table
     */
    public Table getTable() {
      return table;
    }


    /**
     * @param table the table to set
     */
    public void setTable(Table table) {
      this.table = table;
    }


    /**
     * @return the rowData
     */
    public Object[] getRowData() {
      return rowData;
    }


    /**
     * @param rowData the rowData to set
     */
    public void setRowData(Object[] rowData) {
      this.rowData = rowData;
    }


    public Object get(int index) {
      return rowData[index];
    }


    public Object get(String columnName) {
      return get(getTable().getIndexForColumn(columnName));
    }
  }

  static interface IPredicate<TTargetType> {
    boolean evaluate(TTargetType argument);
  }

  static class JoinOperation {
    Table left;
    Table right;

    List<IPredicate<Pair<DataRow>>> joinPredicates = new LinkedList<IPredicate<Pair<DataRow>>>();


    /**
     * @param left
     * @param right
     */
    public JoinOperation(Table left, Table right) {
      super();
      this.left = left;
      this.right = right;
    }


    public Table toTable(String joinTableName) {
      Table joinResult = new Table(joinTableName);
      mergeColumDefinitions(left, right, joinResult);

      for (DataRow leftDataRow : getLeft()) {
        for (DataRow rigthDataRow : getRight()) {
          boolean predicateMatches = true;
          for (IPredicate<Pair<DataRow>> predicate : joinPredicates) {
            predicateMatches &= predicate.evaluate(new Pair<DataRow>(leftDataRow, rigthDataRow));
          }
          if (predicateMatches) {
            DataRow joinedDataRow = createNewDataRowByJoining(leftDataRow, rigthDataRow, joinResult);
            joinResult.getDataRows().add(joinedDataRow);
          }
        }
      }
      return joinResult;
    }


    private void mergeColumDefinitions(Table leftTable, Table rigthTable, Table joinResult) {
      Set<Column> columns = new LinkedHashSet<Column>();
      int position = 0;
      for (Column column : leftTable.getColumns()) {
        columns.add(new Column(column.getQualifiedName(), position++, column.getType(), joinResult));
      }
      for (Column column : rigthTable.getColumns()) {
        columns.add(new Column(column.getQualifiedName(), position++, column.getType(), joinResult));
      }
      joinResult.setColumns(columns);
    }


    public JoinOperation on(IPredicate predicate) {
      joinPredicates.add(predicate);
      return this;
    }


    public DataRow createNewDataRowByJoining(DataRow leftDataRow, DataRow rigthDataRow, Table resultTable) {
      DataRow newDataRow = new DataRow(resultTable);
      System.arraycopy(leftDataRow.getRowData(), 0, newDataRow.getRowData(), 0, leftDataRow.getRowData().length);
      System.arraycopy(rigthDataRow.getRowData(), 0, newDataRow.getRowData(), leftDataRow.getRowData().length,
        rigthDataRow.getRowData().length);
      return newDataRow;
    }


    /**
     * @return the left
     */
    public Table getLeft() {
      return left;
    }


    /**
     * @param left the left to set
     */
    public void setLeft(Table left) {
      this.left = left;
    }


    /**
     * @return the right
     */
    public Table getRight() {
      return right;
    }


    /**
     * @param right the right to set
     */
    public void setRight(Table right) {
      this.right = right;
    }
  }

  static class Pair<TTargetType> {
    public Pair(TTargetType left, TTargetType rigth) {
      this.left = left;
      this.rigth = rigth;
    }

    TTargetType left;
    TTargetType rigth;
  }

}

Table1.csv:
Code:
ID;COLUMN1;COLUMN2
1;C;D1
2;C;D2
3;C;D3
4;C;D4
5;C;D5
6;C;D6
7;C;D7
8;C;D8
9;C;D9
10;C;D10
11;D;D11
12;D;D12
13;D;D13
14;D;D14
15;D;D15
16;D;D16
17;D;D17
18;D;D18
19;D;D19
20;D;D20

Table2.csv:
Code:
ID;COLUMN1;COLUMN2
1;C;XXX
2;D;YYY

Ausgabe:
Code:
table1.ID, table1.COLUMN1, table1.COLUMN2, table2.ID, table2.COLUMN1, table2.COLUMN2, 
1, C, D1, 1, C, XXX, 
2, C, D2, 1, C, XXX, 
3, C, D3, 1, C, XXX, 
4, C, D4, 1, C, XXX, 
5, C, D5, 1, C, XXX, 
6, C, D6, 1, C, XXX, 
7, C, D7, 1, C, XXX, 
8, C, D8, 1, C, XXX, 
9, C, D9, 1, C, XXX, 
10, C, D10, 1, C, XXX, 
11, D, D11, 2, D, YYY, 
12, D, D12, 2, D, YYY, 
13, D, D13, 2, D, YYY, 
14, D, D14, 2, D, YYY, 
15, D, D15, 2, D, YYY, 
16, D, D16, 2, D, YYY, 
17, D, D17, 2, D, YYY, 
18, D, D18, 2, D, YYY, 
19, D, D19, 2, D, YYY, 
20, D, D20, 2, D, YYY,

Oder du nimmst einfach eine Datenbank in die du die beiden CSV Dateien importierst und dann entsprechend über SQL zusammen joinst, die genannte Derby Datenbank (liegt Java 6 bei) wäre da eine Möglichkeit...

Wenn du die Daten jedoch selber zusammen Joinen willst und auf die Reihenfolge der einzelnen Datensätze Einfluss hast, dann kann man die Daten relativ schnell mit einer Schleife zusammen bringen:

(hier mal Beispielhaft)
Java:
/**
 * 
 */
package de.tutorials;

import java.util.ArrayList;
import java.util.List;

/**
 * @author Tom
 */
public class AnotherInMemoryJoinExample {

  /**
   * @param args
   */
  public static void main(String[] args) {
    Integer[][] table1 = { { 1, 2 }, { 2, 2 }, { 3, 3 }, { 4, 3 } };
    Integer[][] table2 = { { 2, 1000 }, { 3, 2000 } };

    Integer[][] result = join(table1, table2, new Integer[]{1,0});
    for(int i = 0; i< result.length;i++){
      for(int j = 0; j < result[i].length;j++){
        System.out.print(result[i][j]);
        System.out.print(" ");
      }
      System.out.println();
    }
  }


  private static Integer[][] join(Integer[][] table1, Integer[][] table2, Integer[] joinColumnIndexes) {
    List<Integer[]> rows = new ArrayList<Integer[]>();

    int currentTable1Index = 0;
    int currentTable2Index = 0;

    while (currentTable1Index < table1.length && currentTable2Index < table2.length) {
      Integer value1 = table1[currentTable1Index][joinColumnIndexes[0]];
      Integer value2 = table2[currentTable2Index][joinColumnIndexes[1]];
      if (value1.equals(value2)) {
        Integer[] row = new Integer[table1[0].length + table2[0].length];
        System.arraycopy(table1[currentTable1Index], 0, row, 0, table1[0].length);
        System.arraycopy(table2[currentTable2Index], 0, row, table1[0].length, table2[0].length);
        rows.add(row);
        currentTable1Index++;
      }else{
       currentTable2Index++; 
      }
    }
    
    Integer[][] result = new Integer[rows.size()][];
    rows.toArray(result);
    return result;
  }

}

Ausgabe:
Code:
1 2 2 1000 
2 2 2 1000 
3 3 3 2000 
4 3 3 2000

Wie gesagt Voraussetzung hierfür ist das Tabelle1 / Tabelle2 jeweils nach den Join Spalten aufsteigend (bzw. entsprechend) sortiert sind.

Gruß Tom
 
Zurück