I created a query on MySQL workbench, it worked fine, but when I tried to show that query on Java it does not work. I'm new to this, and using classicmodels Db. The following query that worked on workbench:
select c.customerNumber, c.customerName,
o.orderNumber,
d.productCode, d.quantityOrdered, d.priceEach, (d.quantityOrdered * d.priceEach) as totalPrice,
e.employeeNumber, e.lastName, ((d.quantityOrdered * d.priceEach)*0.01) as commission
from customers as c inner join orders as o on c.customerNumber=o.customerNumber inner join
orderdetails as d on o.orderNumber=d.orderNumber
inner join employees as e on c.salesRepEmployeeNumber=e.employeeNumber group by productCode;
'486', 'Motor Mint Distributors Inc.', '10109', 'S18_1129', '26', '117.48', '3054.48', '1323', 'Vanauf', '30.5448'
Here is my Java code:
public void query() {
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection(urlConn, user, passWord);
pdState = conn.prepareStatement("SELECT c.customerNumber, c.customerName,o.orderNumber,"
+ " d.productCode, d.quantityOrdered, d.priceEach,(d.quantityOrdered * d.priceEach) as totalPrice,"
+ " e.employeeNumber, e.lastName,((d.quantityOrdered * d.priceEach)*0.01) as commission"
+ " FROM customers as c inner join orders as o on c.customerNumber=o.customerNumber"
+ " inner join orderdetails as d on o.orderNumber=d.orderNumber"
+ " inner join employees as e on c.salesRepEmployeeNumber=e.employeeNumbergroup by productCode");
rSet = pdState.executeQuery();
ResultSetMetaData rsmd = rSet.getMetaData();
c = rsmd.getColumnCount();
DefaultTableModel dtModel = (DefaultTableModel) tblQuery.getModel();
dtModel.setRowCount(0);
while (rSet.next()) {
#SuppressWarnings("UseOfObsoleteCollectionType")
Vector vector = new Vector();
for (int i = 1; i <= c; i++) {
vector.add(rSet.getString("customerNumber"));
vector.add(rSet.getString("customerName"));
vector.add(rSet.getString("orderNumber"));
vector.add(rSet.getString("productCode"));
vector.add(rSet.getString("quantityOrdered"));
vector.add(rSet.getString("priceEach"));
vector.add(rSet.getString("totalPrice"));
vector.add(rSet.getString("employeeNumber"));
vector.add(rSet.getString("lastName"));
vector.add(rSet.getString("commission"));
}//end of for loop
dtModel.addRow(vector);
}//end of while loop
} catch (ClassNotFoundException | SQLException e) {
e.getMessage();
}//end of try and catch block
}//end of query
The problem here is the group by clause. You've grouped on one field, and failed to ensure all the other fields are either uniquely determined by that field, or grouped functions. Remove the group by productCode and everything should work.
I think the reason it "worked" in MySQL workbench is probably that there is an option you can set (but probably should not) that allows improper grouped fields to "work" (I think by just picking one of many values).
As an example of a query that might work, the following should report the commission each employee has earned by product sold. Since the customer is irrelevant to that information, that table wasn't queried.
select d.productCode, e.employeeNumber, e.lastName,
sum((d.quantityOrdered * d.priceEach)*0.01) as commission
from orders as o
inner join orderdetails as d on o.orderNumber=d.orderNumber
inner join employees as e on c.salesRepEmployeeNumber=e.employeeNumber
group by productCode, employeeNumber;
Related
I'm new to java and I need help with displaying a joined table/query in jtable.
First, I have done displaying data from 1 table which is:
Select data from 1 table
insert the result to its entity and insert each one of it to a List
return the list to view and insert row to jtable
I am using a DAO pattern, which has a factory, interface, implement, entity and view.
So what if I select data from other table?
Here is my get method in implement for getting book
public List get(String find) {
try {
ps = db.connect().prepareStatement("SELECT * FROM books WHERE title like ? ");
ps.setString(1, "%" + find + "%");
status = db.execute(ps);
if (status) {
books = db.get_result();
listBooks = new ArrayList<>();
while (books.next()) {
entity_books b = new entity_books();
b.setId(books.getInt(1));
b.setId_category(books.getInt(2));
b.setTitle(books.getString(3));
listBooks.add(b);
}
books.close();
return listBooks;
}
} catch (SQLException e) {
System.out.println(e.getMessage());
}
return null;
}
and then in my view:
listBooks = booksDAO.get(find.getText());
model = (DefaultTableModel) book_table.getModel();
model.setRowCount(0);
listBooks.forEach((data) -> {
model.addRow(new Object[]{
data.getId(),
data.getId_category(),
data.getTitle(),
});
});
This works fine, but I want the query to join table so I can see the category name instead of just ID category. I can do the query, but how do I apply that to my code?
Here is the query for joined table
select title,category from book b
join category c on c.id = b.id_category
Normally if I select only 1 table, I would insert it to its entity ( book table -> book entity ), so how do I handle this with multiple tables?
I didn't use prepared statement, but this code works on my end.
String sql = "SELECT * FROM customer c JOIN company cmp ON c.company_idcompany = cmp.idcompany";
ResultSet rs = stmt.executeQuery(sql);
//STEP 5: Extract data from result set
while (rs.next()) {
//Retrieve this from customer table
int id = rs.getInt("idcustomer");
//Retrieve this from customer table
String username = rs.getString("company_username");
//Display values
System.out.println("ID: " + id);
System.out.println("Username: " + username);
}
I am trying to read a temporary variable created from my MySql query as follows:
String name = "";
selectQuery = "select (select "
+ "CONCAT(s.firstname,\" \",s.surname) "
+ "AS name) "
+ "from student s, marks m where m.grade = 'fail'";
try{
pstmt = con.prepareStatement(selectQuery);
rs = pstmt.executeQuery(selectQuery);
int count = 0;
while(rs.next()){
name = rs.getString("name");
System.out.println(++count+". "+name);
}
rs.close();
pstmt.close();
}catch(Exception e){
e.printStackTrace();
}
I get SQLException as column 'name' not found. When I run the query in MySql server it runs fine.
In order for the alias to apply, it must be places outside the nested query's parenthesis, not inside it. However, you could just drop it altogether and just use the concat call directly in the select list.
Two more side notes:
Implicit joins (i.e., placing more than one table in the from list) have been deprecated for quite a while. It's considered a better practice to use explicit joins.
Regardless of the joining syntax you're using, you're missing the join condition.
Using concat_ws instead of concat may save you some hassle with handling the white space yourself.
To make a long story short:
select CONCAT_WS(' ', s.firstname, s.surname) AS name
FROM student s
JOIN marks m ON s.id = m.student_id
WHERE m.grade = 'fail'
I have 3 tables having the following content :
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 am trying to do relational schema on the authors. The objectif is to show the number of publication they have in common. The authors name are parameters, I can have up to 8 names. My code is giving the number of common publication between 2 authors, so i have to loop it. I am currently using a Java loop and SQL statement to do that. Here is the SQL part
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;
}
Here is the loop part (to repeat the SQL when there are more than 2 authors given) and generate the graph :
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);
// /////////////////////////////////////////
}
My code is currently working, but I would like to know if it was possible to increase the performance by passing everything into MySQL, that means that I enter the authors name in parameter and the loop is hangled by MySQL, I check the MySQL procedure but my issue is how to handle the authors names parameter as it is a variable.
One way, in a single statement:
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 = '...'
Another way may be
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 indexes needed:
Author_has_Publication: (author_idAuthor, publication_idPublication)
Author_has_Publication: (publication_idPublication, author_idAuthor)
Author: (name, id)
Note: Each technique can be rather easily extended to more than 2 authors. The second query could even be adapted to "at least 3 of these 5 authors": 5 names in IN and HAVING COUNT(*) >= 3.
I have 2 database tables for my program: GameInfo and Characters.
How this works is that a Game has 4 maps with different names and each character added to the game must be assigned any of the 4 maps. Now I have the sql statement which returns a result set named "Expr1001, of the number of characters on each map. I then need to add this information to a jTable and link up the corresponding amount of each characterson a map, with the mapname.
My ResultSet with the query which returns the amount of characters on each map:
ResultSet qs = dbm.queryDatabase("SELECT Expr1001 FROM (SELECT GameInfo.mapname, SUM(IIF(Map = GameInfo.mapname,1,0)) FROM (SELECT * FROM [Character] INNER JOIN Player ON Character.PlayerID=Player.[ID]) AS A RIGHT JOIN GameInfo ON A.Character.map = GameInfo.mapname GROUP BY GameInfo.mapname) AS [%$###_Alias]");
The whole method which gets the Game Info from the database from the GameInfo table, which comprises of a GameID and MapName only.
public Game[] getGameInfo(){
Game[] arr = null; //Creates an array of Games
try { //getting list from database
ResultSet rs = dbm.queryDatabase("Select Count(GameID) as NumGames from GameInfo" );
//While there are still more rows to read from the database.
rs.next();
int count = rs.getInt("NumGames");
arr = new Game[count];
String sql = "Select * from GameInfo";
// System.out.println(sql);
rs = dbm.queryDatabase(sql);
//Take the info from the current row
//Add the info to the array
ResultSet qs = dbm.queryDatabase("SELECT Expr1001 FROM (SELECT GameInfo.mapname, SUM(IIF(Map = GameInfo.mapname,1,0)) FROM (SELECT * FROM [Character] INNER JOIN Player ON Character.PlayerID=Player.[ID]) AS A RIGHT JOIN GameInfo ON A.Character.map = GameInfo.mapname GROUP BY GameInfo.mapname) AS [%$###_Alias]");
for(int i = 0; rs.next(); i++){
arr[i] = new Game(
rs.getInt("GameInfo.GameID"),
rs.getString("GameInfo.mapname"),
qs.getInt(i));
}//Creates a Game from the currently selected info
} catch (Exception e) {
JOptionPane.showMessageDialog(null, "Failed to get Games");
e.printStackTrace();
}
return arr;
}
}
The data is then added to the jTable which is on a Panel in the GameInfoPanel class:
public void refreshTable() {
//remove old stuff
refreshing = true;
Game[] arr = gim.getGameInfo();
DefaultTableModel model = (DefaultTableModel) GameInfoTable.getModel();
while (model.getRowCount() > 0) {
model.removeRow(0);
}
for (int i = 0; i < arr.length; i++) {
model.addRow(new Object[]{
arr[i].getNumberOfCharacters(),
arr[i].getID(),
arr[i].getMapName()});
}
refreshing = false;
//load new data from database using manager
}
I keep getting the error which points to the ResultSet qs line: "user lacks privilege or object not found: A.CHARACTER.MAP" when I try and run the program even though when I copy this statement into Microsoft Access and run it, it's fine.
Help please!
Thanks.
(I am still at school so not really a genius on this at all so please have mercy if I've done some stupid things)
Don't run a select count(*) first to get the number of games for allocating an array. Build you result in a List, which will auto-expand as needed. You can always convert the list to an array later, if needed.
Don't run two queries when one can do the job, especially when you already join to the table in question.
Your SQL is unreadable, so here it is in a more readable format:
String sql = "SELECT Expr1001" +
" FROM (SELECT GameInfo.mapname" +
", SUM(IIF(Map = GameInfo.mapname,1,0))" +
" FROM (SELECT *" +
" FROM [Character]" +
" INNER JOIN Player ON Character.PlayerID=Player.[ID]" +
") AS A" +
" RIGHT JOIN GameInfo ON A.Character.map = GameInfo.mapname" +
" GROUP BY GameInfo.mapname" +
") AS [%$###_Alias]";
The outer query does nothing. Get rid of it.
Don't SELECT *. Select the columns you want, i.e. Character.map.
Since you want GameID, add it to the GROUP BY.
Specify an alias for the SUM value.
public Game[] getGameInfo(){
String sql = " SELECT GameInfo.GameID" +
", GameInfo.mapname" +
", SUM(IIF(C.map = GameInfo.mapname,1,0)) AS CharacterCount" +
" FROM ( SELECT Character.map" +
" FROM [Character]" +
" JOIN Player ON Player.[ID] = Character.PlayerID" +
") C" +
" RIGHT JOIN GameInfo ON GameInfo.mapname = C.map" +
" GROUP BY GameInfo.GameID" +
", GameInfo.mapname";
try (ResultSet rs = dbm.queryDatabase(sql)) {
List<Game> games = new ArrayList<>();
while (rs.next())
games.add(new Game(rs.getInt("GameID"),
rs.getString("mapname"),
rs.getInt("CharacterCount")));
return games.toArray(new Game[games.size()]);
} catch (Exception e) {
JOptionPane.showMessageDialog(null, "Failed to get Games");
e.printStackTrace();
return null;
}
}
i'm building my JTable in a java application so that i can query my sql database according to different criteria i will select on several comboboxes. This is my entire database viewed from PHPMyAdmin,
http://s21.postimg.org/tcnsklzk7/base_de_datos.png
i'm trying to print it in my JTable but it only works when there's no null values in any of the rows printed like in the rows of Agapito Noguera, but if i'm showing results that include NULL like in Yasuri Gonzales it doesn't show anything in the JTable it only says null in the output screen like this
http://s15.postimg.org/nxsrjawgr/null_programa.png
this is the code that handles the output of the rows:
String query="SELECT `nombre solicitante`,`apellido solicitante`,`nombre status`,`nombre canal`,"+
"`nombre municipio`,`gmvv`,`0800mihogar`,`nombre situacion` FROM `solicitante` LEFT OUTER JOIN"+
" `solicitud` ON `solicitante`.`cedula solicitante`=`solicitud`.`cedula solicitante` "+
"LEFT OUTER JOIN `canal` ON `solicitud`.`id canal`=`canal`.`id canal` LEFT OUTER JOIN `status` "+
"ON `solicitud`.`id status`=`status`.`id status` LEFT OUTER JOIN `municipio` ON "+
"`solicitud`.`id municipio`=`municipio`.`id municipio` LEFT OUTER JOIN `situacion solicitante`"+
" ON `solicitud`.`id solicitud`=`situacion solicitante`.`id solicitud` LEFT JOIN `situacion` ON"+
" `situacion solicitante`.`id situacion`=`situacion`.`id situacion` "
+ "WHERE `solicitante`.`nombre solicitante`='yndra' AND `situacion`.`id situacion`=1 "
+ "ORDER BY `nombre solicitante`,`apellido solicitante`";
ResultSet rs = stm.executeQuery(query);
ResultSetMetaData rsmd = rs.getMetaData();
int columnas = rsmd.getColumnCount();
ArrayList<Object[]> data=new ArrayList<>();
while(rs.next()){
Object[] rows=new Object[columnas];
for (int i = 0; i < columnas;i++) {
rows[i]=rs.getObject(i+1).toString();
}
data.add(rows);
}
for (int i=0; i<data.size(); i++){
dtm.addRow(data.get(i));
}
how can i print the NULL fields in my JTable?