2016-11-10 4 views
0

Ich habe 3 Tabellen mit folgendem Inhalt:Schleife MySQL läuft mit java

Author 
idAuthor INT 
name VARCHAR 

Publication 
idPublication INT 
Title VARCHAR 
Date YEAR 
Type VARCHAR 
Conference 

author_has_publication 
author_idAuthor INT 
publication_idPublication INT 

I relationales Schema zu den Autoren zu tun versuchen. Das Ziel ist es, die Anzahl der Publikationen zu zeigen, die sie gemeinsam haben. Der Name des Autors ist Parameter, ich kann bis zu 8 Namen haben. Mein Code gibt die Anzahl der gemeinsamen Veröffentlichungen zwischen zwei Autoren an, also muss ich sie wiederholen. Ich verwende derzeit eine Java-Schleife und eine SQL-Anweisung, um das zu tun. Hier ist die SQL Teil

private int runQuery(String a1, String a2){ // a1 author 1 and a2 author 2 
     try { 
      auth1 = new ArrayList<String>(); 
      Class.forName("com.mysql.jdbc.Driver"); 
      Connection connection = DriverManager.getConnection(
        "jdbc:mysql://localhost:3306/mydb", "root", "ROOT"); 
      Statement stmt = connection.createStatement(); 
      long start = System.currentTimeMillis(); 


      String queryUpdate1 = "DROP TABLE IF EXISTS temp1;"; 
      String queryUpdate2 = "DROP TABLE IF EXISTS temp2;"; 
      String queryUpdate3 = "CREATE TEMPORARY TABLE IF NOT EXISTS temp1 AS (SELECT Author.name, Publication.idPublication, Publication.title FROM Author INNER JOIN Author_has_Publication ON Author_has_Publication.author_idAuthor=author.idAuthor INNER JOIN Publication ON Author_has_Publication.publication_idPublication=publication.idPublication WHERE Author.name='"+ a1+"');"; 
      String queryUpdate4 = "CREATE TEMPORARY TABLE IF NOT EXISTS temp2 AS (SELECT Author.name, Publication.idPublication, Publication.title FROM Author INNER JOIN Author_has_Publication ON Author_has_Publication.author_idAuthor=author.idAuthor INNER JOIN Publication ON Author_has_Publication.publication_idPublication=publication.idPublication WHERE Author.name='"+ a2+"');"; 
      String query = "SELECT COUNT(*) FROM (SELECT temp1.title from temp1 INNER JOIN temp2 on temp1.idPublication = temp2.idPublication) as t;"; 

      stmt.executeUpdate(queryUpdate1); 
      stmt.executeUpdate(queryUpdate2); 
      stmt.executeUpdate(queryUpdate3); 
      stmt.executeUpdate(queryUpdate4); 
      ResultSet rs = stmt.executeQuery(query); 
      int result = -1; 
      while (rs.next()) { 
       result = rs.getInt(1); 
      } 

      System.out.println("result = " + result); 
      long end = System.currentTimeMillis() - start; 
      queryTimeLabel.setText("Query Execution Time :"+end); 
      connection.close(); 
      return result; 
     } catch (Exception e) { 
      System.out.println(e); 
     } 
     return -1; 
    } 

Hier wird die Schleife Teil (die SQL zu wiederholen, wenn es mehr als zwei Autoren gegeben) und erzeugen Sie die Grafik:

public void actionPerformed(ActionEvent e) { 

    graph = new mxGraph(); 
    Object parent = graph.getDefaultParent(); 
    authVertex = getAuthors(); 



    // /////////////////////////////////// 
    // CREATES GRAPH, Graph only shows up after you resize the window 
    graph.getModel().beginUpdate(); 
    try { 

     int i = 0; 
     for(String a: authVertex.keySet()){ 
      int j = 0; 
      for(String b: authVertex.keySet()){ 
       if(j > i) { 
        graph.insertEdge(parent, null, String.valueOf(runQuery(a,b)), authVertex.get(a), authVertex.get(b)); // loop the SQL statement 2 by 2. 
       } 
       j++; 
      } 
      i++; 
     } 
    } finally { 
     graph.getModel().endUpdate(); 
    } 

    graphComponent = new mxGraphComponent(graph); 
    graphPan.removeAll(); 
    graphPan.add(graphComponent); 
    setVisible(true); 
    // ///////////////////////////////////////// 


} 

Mein Code arbeitet derzeit, aber Ich würde gerne wissen, ob es möglich ist, die Leistung zu erhöhen, indem ich alles in MySQL übergebe, das heißt, ich gebe den Namen des Autors in Parameter ein und die Schleife wird von MySQL gehängt, ich überprüfe die MySQL - Prozedur, aber mein Problem ist, wie ich mit dem umgehen soll authors benennt Parameter als eine Variable.

+0

Lesen Sie weiter auf JOIN – e4c5

+0

Sie sollten 'Prepared' Anweisungen verwenden. Wenn Sie nicht darüber nachgedacht haben, kann ich eine Antwort darüber schreiben, und mehrere Leistungsverbesserungstechniken. – GOXR3PLUS

+0

Ich denke, Sie können es mit Unterabfragen und Joins tun. – chomnoue

Antwort

0

Eine Möglichkeit, in einer einzigen Anweisung:

SELECT COUNT(*) 
    FROM Author_has_Publication AS ap1 
    JOIN Author_has_Publication AS ap2 ON ap1.publication_idPublication = 
              ap2.publication_idPublication 
    JOIN Author AS a1 ON ap1.author_idAuthor = a1.id_Author 
    JOIN Author AS a2 ON ap2.author_idAuthor = a2.id_Author 
    WHERE a1.name = '...' 
     AND a2.name = '...' 

Ein anderer Weg sein kann

SELECT COUNT(*) 
    FROM 
    (
     SELECT ahp.publication_idPublication, COUNT(*) 
      FROM Author_has_Publication AS ahp 
      JOIN Author AS a ON a.id_Author = ahp.author_idAuthor 
      WHERE a.name IN ('...', '...') 
      GROUP BY ahp.publication_idPublication 
      HAVING COUNT(*) = 2 -- Number of authors 
    ) x 

Composite-Indizes benötigt:

Author_has_Publication: (author_idAuthor, publication_idPublication) 
Author_has_Publication: (publication_idPublication, author_idAuthor) 
Author: (name, id) 

Hinweis: Jede Technik relativ leicht erweitert werden kann, an mehr als 2 Autoren. Die zweite Abfrage könnte sogar an "mindestens 3 dieser 5 Autoren" angepasst werden: 5 Namen in IN und HAVING COUNT(*) >= 3.