# Tabellen verbinden



## Flexer (16. Sep 2015)

Hallo ich bräuchte mal eure hilfe. wie kann ich von zwei methoden die jeweils ein resultset ausführen zusammenbringen. die ein methode liest die teilnehemr aus der db, die andere liest die provider aus der db. die erste liefert eine int wert zurück und die zweite einen string. ich würde gerne wenn die erste methode den wert 1 hat ihr einen bestimmten provider geben.
Ich habe momentan keine plan ob ich die query zusammenfürhren kann und dann die methode aurufen kann und wie das get jemand plan ??? lg

```
public static Vector<?> getRefModulesByTestcaseId(int testcaseId) {
     Statement statementS = null;
     Statement statementP = null;
     Vector<Object> list = new Vector<Object>();

     try {
       int subscribers = 0;
       ResultSet resultSetS = null;
       mutex.acquire();
       statementS = DbUtilities.getConnection().createStatement();
       statementP = DbUtilities.getConnection().createStatement();
      
       String queryS = "SELECT subscribers FROM ST_TestcaseSubscribers"
          + " WHERE tcId = " + testcaseId;

       resultSetS = statementS.executeQuery(queryS);

       // Hole Anzahl der Teilnehmer und schreibe in Variable
       if (resultSetS.next()) {
         subscribers = Integer.parseInt(resultSetS.getString("subscribers"));
      }
       for (int i = 1; i <= subscribers; i++) {
         //list.add(""+i);
         /*if(i==1){
       //hier probiere ich schon sowas wie
      //  if(resultSet.getString("device").equals("DUT")){
           list.add(new AccessoryParameter("Provider", resultSet.getString("Provider"),  
           "String"));
         }*/
       }    
     } catch (Exception ex) {
       TimLogging.addError(ex.toString());
       ex.printStackTrace();

     } finally {
       try {
         statementS.close();
         statementP.close();
         mutex.release();
       } catch (Exception ex) {
         TimLogging.addError(ex.toString());
         ex.printStackTrace();
       }
     }
     return list;
   }
//--------------------------------------------------------------------------------------------------
   public static Vector<AccessoryParameter> getProviderByTestcaseId(int testcaseId) {
     Statement statement = null;
     Vector<AccessoryParameter> list = new Vector<AccessoryParameter>();

     try {
       ResultSet resultSet = null;
      
       mutex.acquire();
       statement = DbUtilities.getConnection().createStatement();
       String query = "SELECT device, Provider FROM ST_xTestcaseSubscriberProvider WHERE"
       + " testcaseID = " + testcaseId;

       resultSet = statement.executeQuery(query);
  
       while (resultSet.next()) {
         if(resultSet.getString("device").equals("DUT")){
           list.add(new AccessoryParameter("Provider", resultSet.getString("Provider"), "String"));
           System.out.println("Inhalt der Provider R1" + list.toString());
         }if(resultSet.getString("device").equals("remote1")){
           list.add(new AccessoryParameter("Provider", resultSet.getString("Provider"), "String"));
         }
       }
      
     } catch (Exception ex) {
       TimLogging.addError(ex.toString());
       ex.printStackTrace();

     } finally {
       try {
         statement.close();
         mutex.release();
       } catch (Exception ex) {
         TimLogging.addError(ex.toString());
         ex.printStackTrace();
       }
     }
     return list;
   }
```


----------



## Joose (16. Sep 2015)

Was du suchst sind JOINS, damit kannst du zusammengehörende Daten von 2 Tabellen in einem SELECT suchen. 
http://www.w3schools.com/sql/sql_join.asp

Tipp: Verwende PreparedStatements, dadurch kannst du SQLInjection verhindern. So wie es jetzt ist wäre dein Code gefährtet.


----------



## Flexer (16. Sep 2015)

Hi danke für dein ratschlag ich habe mich mal schlau gemacht und eine neue query erezeugt bekomme aber eine fehlermeldung error : sql syntax near from. was mach ich verkehrt?


```
String query = "SELECT ST_TestcaseSimProvider.Provider, ST_xTestcaseDeviceProviders.device, ST_xTestcaseDeviceProviders.Provider"+
  "FROM ST_TestcaseSimProvider INNER JOIN ST_xTestcaseDeviceProviders"+
    "ON ST_TestcaseSimProvider.testcaseID= ST_xTestcaseDeviceProviders.testcaseID "+
  "WHERE ST_TestcaseSimProvider.testcaseID = " + testcaseId;
```

habe ich nach dem w3school examplezusammengebaut, vieleicht kannst du mir helfen, achso jetzt hast du mich auf preparedaufmerksam gemacht wie würde es ausserdem  damit funktionieren? äre echt cool wenn das oben zum verständnis für mich funzt und noch ein mit prepared.
danke und beste grüße


----------



## Thallius (16. Sep 2015)

Wenn du dir einfach mal den String ausgeben läst solltest du sofort den Fehler sehen.

Gruß

Claus


----------



## Joose (17. Sep 2015)

Um den Syntaxfehler hat dir Thallius schon gesagt wie du den findest

Für PreparedStatement schau einfach mal hier vorbei:
http://docs.oracle.com/javase/tutorial/jdbc/basics/prepared.html


----------



## Flexer (17. Sep 2015)

hallo danke für den tipp habe die query auch mit der inner join variante hinbekommen.
aber ich habe jetzt ein neues problem was schwierig ist zu erklären aber ich probiere es mal.
Ich glaube es handelt sich auch um ein verständnis problem und ich möchte von euch wissen obe es überhaupt möglich ist.

also folgendes ich habe oben in den quellcode eine methode die heist "getRefModulesByTestcaseId" deren query habe ich ge "joint" mit der query ist man jetzt in der lage die anzahl der provider zu zählen.

das ergebnis wird dann in einer liste gespeichert s.o.

bsp: anzahl 2 String : Alice , Peter  durch meine abfrage wird immer alles gedoppelt.

```
for (int i = 1; i <= subscribers; i++) {
         System.out.println("Anzahl" + i + " teilnehmer"+ subscribers);
         if(i == 1){
           list.add(new AccessoryParameter("Provider", resultSetS.getString("Provider"), "String"));
           System.out.println("hier muss teilnehmer 1 stehen"+ i);
         }
         if(i == 2 && resultSetS.next() == resultSetS.getString("device").equals("remote1")){
           list.add(new AccessoryParameter("Provider", resultSetS.getString("Provider"), "String"));
          // return WmRdItStDbRemotes.getProviderByTestcaseIdR1(testcaseId);
         }
       }
```
Ausgabe der Liste oder besser gesagt inhalt:
1 : Alice, Peter
2 : Alice, Peter

ich würde gerne haben

1: alice
2: peter

das problem ist die methode getrefmodulesbytescaseId wird von einer anderen  liste aufgerufen und es wi wird immer nur der erste wert "Alice betrachtet".

Beste Grüße


----------



## Thallius (17. Sep 2015)

Ich kapiere ehrlich gesagt überhaupt nix aber wenn du doppelte Werte aus dem Query zusammen fassen willst, dann geht das mit GROUP BY


----------



## Joose (18. Sep 2015)

Ich muss ehrlich gesagt auch gestehen das ich nicht weiß wo genau das Problem liegt.
Probiere es doch nochmal grundlich zu erklären: Wie schaut der Aufbau der DB aus, welches Query führst du aus, was steht im ResultSet drinnen, wie wird deine Liste befüllt


----------



## Flexer (18. Sep 2015)

Ha , wusst ich doch das es nicht einfach zu verstehen ist und wenn ich nicht selber mit dem problem beschäftigt wär würde ich es auch selber nicht verstehn. nein spass beisseite. Also folgendes: Aufbau der beiden tabellen.

tabelle 1: ST_TestcaseSubscribers(2 Columns)                 
tabelle 2 : ST_xTestcaseSubscriberProvider (3 columns)

tcid   ||       subscribers   
30    ||               2                            
testcaseID   ||      device    ||     Provider
30             ||             DUT       ||         alice         
               ||             remote1     ||      peter


die Methode die jetzt betrachtet wird ist diese die auch die query der beiden tabellen joint.
habe java kommentare in der methode drin was genau passiert

```
public static Vector<AccessoryParameter> getRefModulesByTestcaseId(int testcaseId) {
     Statement statementS = null;
     /*hier steht der Inhalt der Liste drin*/
     Vector<AccessoryParameter> list = new Vector<AccessoryParameter>();


     try {
       int subscribers = 0;
       ResultSet resultSetS = null;
       mutex.acquire();
       statementS = DbUtilities.getConnection().createStatement();
 
        /* Query die die Werte ausliest */
       String queryS = "SELECT Provider, device, subscribers FROM ST_xTestcaseSubscriberProvider inner join ST_TestcaseSubscribers on ST_xTestcaseSubscriberProvider.testcaseID = ST_TestcaseSubscribers.tcid WHERE ST_xTestcaseSubscriberProvider.testcaseID = "+testcaseId;

       resultSetS = statementS.executeQuery(queryS);

       // Hole Anzahl der Teilnehmer und schreibe in Variable
       if (resultSetS.next()) {
         subscribers = Integer.parseInt(resultSetS.getString("subscribers"));
         System.out.println("total "+list.toString()+ list.size());
      }
       /*erster versuch einen subscriber einen provider zuzuweisen*/
     /*   while (resultSetS.next()) {
         if(resultSetS.getString("device").equals("remote1")){
           list.add(new AccessoryParameter("Provider", resultSetS.getString("Provider"), "String"));
           System.out.println("Inhalt der Provider R1" + list.toString());
         }
         else if(resultSetS.getString("device").equals("remote2")){
           list.add(new AccessoryParameter("Provider", resultSetS.getString("Provider"), "String"));
           System.out.println("Inhalt der Provider R1" + list.toString());
         }
   
       }*/
 
 
       for (int i = 1; i <= subscribers; i++) {
         System.out.println("Anzahl" + i + " teilnehmer"+ subscribers);
         if(i == 1){
           list.add(new AccessoryParameter("Provider", resultSetS.getString("Provider"), "String"));
           System.out.println("hier muss provider mit  1 stehen (alice)"+ i);
     
          //list.add(1, new AccessoryParameter("Provider", resultSetS.getString("Provider"), "String"));
         }
         if(i == 2 && resultSetS.next() == resultSetS.getString("device").equals("remote1")){
           list.add(0,new AccessoryParameter("Provider", resultSetS.getString("Provider"), "String"));
     
         }
       }

       /*Dadurch das in der in der subscriber tabelle die zahl 2  steht  wird die liste 2 mal mit folgenden werten befüllt
          1.  [alice, peter]   ich möchte aber folgendes haben 1. [alice]
          2.  [alice, peter]                                                     2.  [peter]                         */

/*Bibt es da nicht eine Möglichkeit einem teilenehmer eine bestimmten index der liste zuzuweisen bsp:
    1 == alice und 2 == peter*/
 
     } catch (Exception ex) {
       TimLogging.addError(ex.toString());
       ex.printStackTrace();

     } finally {
       try {
         statementS.close();
         mutex.release();
       } catch (Exception ex) {
         TimLogging.addError(ex.toString());
         ex.printStackTrace();
       }
     }
     return list; // Inhalt der Liste [alice, peter]
   }
```

ich hoffe konnte mich verständlich ausdrücken beste grüße


----------



## Joose (18. Sep 2015)

Ich finde du gehst hier falsch an das Problem ran.

Die Tabelle "ST_TestcaseSubscribers" enthält nur die Daten wieviele Teilnehmer ein Testcase hat.
Es ist unnötig diese Information explizit in der Datenbank zu speichern, da durch die Einträge in der Tabelle "ST_xTestcaseSubscriberProvider" schon auf die Anzahl schließen kannst.
> SELECT COUNT(*) FROM ST_xTestcaseSubscriberProvider WHERE testcaseID = ?
Mit dieser Abfrage bekommst du die Anzahl der Datensätze die es für den Testcase gibt = Anzahl der Teilnehmer
(So würdest du dir theoretisch die Tabelle und den JOIN ersparen)

Und selbst wenn es einen Grund geben sollte die Anzahl explizit zu speichern so macht ein JOIN in diesem Fall keinen Sinn.
Sondern Frage diese Daten getrennt ab. Zuerst fragst du die Anzahl der Teilnehmer ab und dann die Teilnehmer.
Aber ansonsten schaut dein Code schon richtig aus, ich würde jetzt eher vermuten das die Daten falsch in der DB stehen.

Hast du schon mal mit dem Debugger geschaut was du bei "resultSetS.getString("Provider")" zurück bekommst?
Alice?
Alice, Peter?


----------



## Flexer (18. Sep 2015)

ja habe ich reingeschaut und das "resultSetS.getString("Provider")" ist wirklich für jede abfrage einzeln vorhanden.

```
for (int i = 1; i <= subscribers; i++) {
         System.out.println("Anzahl" + i + " teilnehmer"+ subscribers);
         if(i == 1){
           list.add(new AccessoryParameter("Provider", resultSetS.getString("Provider"), "String"));
           System.out.println("hier muss provider mit  1 stehen (alice)"+ i);
          // Hier steht wirklich alice drin alleine     
          //list.add(1, new AccessoryParameter("Provider", resultSetS.getString("Provider"), "String"));
         }
         if(i == 2 && resultSetS.next() == resultSetS.getString("device").equals("remote1")){
           list.add(0,new AccessoryParameter("Provider", resultSetS.getString("Provider"), "String"));
           // Hier steht wirklich alice peter alleine  
         }
       }
```

ich weiss auch woran es liegt : es ist die return anweisung "return list" deswegen [alice, peter]
ich müsste einen weg finden jedes einzelne element abzufragen, ich glaube hierfür eignet sich ein iterator oder gibt es was besseres?


----------



## Joose (21. Sep 2015)

Flexer hat gesagt.:


> ich weiss auch woran es liegt : es ist die return anweisung "return list" deswegen [alice, peter]
> ich müsste einen weg finden jedes einzelne element abzufragen, ich glaube hierfür eignet sich ein iterator oder gibt es was besseres?



Wo liegt das Problem? Du hast einen Vector mit X Einträgen du kannst über diesen Vector iterieren und jeden Eintrag einzeln verarbeiten.


----------



## Flexer (21. Sep 2015)

Hi habe ich soweit probiert aber ich glaube ich verwende den iterator nicht richtig, vielleicht hast du einen lösungsvorschlag? du erinnerst dich doch an die methode getrefmodules, wo die query ausgelesen wird, diese methode wird übergeben. ich habe wieder kommentare im quellcode reingeschrieben. ich glaube du müsstest das problem auf anhieb finden.


```
Vector<?> refModules = WmRdItStDb.getRefModulesByTestcaseId(this.testcaseInfo.getTestcaseId());
    
     System.out.println("Ausgabe von Refmodules steht auch wirklich  [alice, peter] "+ refModules.toString());
    
     for(Iterator iter = refModules.iterator(); iter.hasNext();){
     //for (int i = 0; i < refModules.size(); i++) { liefert nur die größe zurück
       RefModule refModule = new RefModule();
      
       //if(i == 0){ war mein erster versuch liest aber immer nur die erste stelle der liste
       if (iter.next() != null) {
         iter.remove();
         /*
          * Teilnehmer 1 muss alle Moduleigenschaften, die vom Testlauf
          * gefordert sind, vorweisen.
          */
         TimLogging.addDebug(2, " Adding reference modules (Product/HW/SW)...");
         if (this.testcaseInfo.getTestrunId() > 0) {
           refModule.setProduct(WmRdItStDb.getProductByTestrunId(this.testcaseInfo.getTestrunId()));
           refModule.setLayout(WmRdItStDb.getHardwareVersionByTestrunId(this.testcaseInfo.getTestrunId()));
           refModule.setSwVersion(WmRdItStDb.getSoftwareVersionByTestrunId(this.testcaseInfo.getTestrunId()));
         } else {
           refModule.setProduct(this.testcaseInfo.getProduct());
           refModule.setLayout(this.testcaseInfo.getHwVersion());
           refModule.setSwVersion(this.testcaseInfo.getSwVersion());
         }
         TimLogging.addDebug(2, "  reference module->product: " + refModule.getProduct());
         TimLogging.addDebug(2, "  reference module->HW: " + refModule.getLayout());
         TimLogging.addDebug(2, "  reference module->SW: " + refModule.getSwVersion());
       }    
       /*
        * CHANGE: Testvoraussetzungen werden nicht mehr aus den
        * RefModul-Tabellen entnommen, sondern aus den in iMaCS zum Test
        * eingetragenen Daten.
        */

       TimLogging.addDebug(2, " Reading SIMs for testcase...");
       Vector<?> simLms = WmRdItStDb.getSimLmsByTestcaseID(this.testcaseInfo.getTestcaseId());
    
       TimLogging.addDebug(2, " Reading Providers for testcase...");
      
       Vector<?> provider = WmRdItStDb.getRefModulesByTestcaseId(this.testcaseInfo.getTestcaseId());
      
    
       System.out.println("Ausgabe von provider"+ provider.toString());
       // SimLM hinzufügen
       /*
        * CHANGE: Spezielle Anforderungen bezüglich SIM-Leistungsmerkmalen
        * gelten nur für Teilnehmer 1(i = 0).
        */
  
       TimLogging.addDebug(2, " Adding SIMs to refModule...");
      
       //if(i == 0){ war mein erster versuch liest aber immer nur die erste stelle der liste
       if (iter.next() != null ) {
         iter.remove();
         for (int j = 0; j < simLms.size(); j++) {
           refModule.addSimLm((AccessoryParameter) simLms.get(j));
           TimLogging.addDebug(2, "  reference module->SIM: " + ((AccessoryParameter)simLms.get(j)).toString());
         }
       }

       // Provider hinzufügen
       TimLogging.addDebug(2, " Adding Providers to refModule...");
       // fügt aber nur den ersten provider hinzu vielleciht muss hier was geändert werden ???????
       for(Iterator iter1 = refModules.iterator(); iter1.hasNext();){
     //   for (int j = 0; j < provider.size(); j++) {
        
         refModule.addSimLm((AccessoryParameter) provider.iterator());
        
         /*Teilnehmer in die Sammlung hinzufügen*/
         TimLogging.addDebug(2, "  reference module->Provider: " + ((AccessoryParameter)provider.iterator()));
         /*Teilnehmer Debug Ausgabe*/
       }
       TimLogging.addDebug(2, " Adding refModule to internal list...");
       listOfRefModules.add(refModule);
     }
     TimLogging.addLog("fetchDataFromDatabase(): successful");
   }
```

grüssle


----------



## Joose (21. Sep 2015)

Hier 2 Links wie du alle Elemente deines Vectors durchgehen kannst:
http://www.java-examples.com/iterate-through-elements-java-vector-using-iterator-example (Iterator Variante)
http://www.java-examples.com/get-size-java-vector-and-loop-through-elements-example (for-Loop)

Damit solltest du weiterkommen.


----------

