Skip to main content



      Home
Home » Eclipse Projects » Eclipse Scout » SQL.selectInto(...) with IN clause and Grouping
SQL.selectInto(...) with IN clause and Grouping [message #1728481] Mon, 04 April 2016 14:36 Go to next message
Eclipse UserFriend
Hi there,

I'm currently investigating a weird problem.

I have got this SQL statement:

SQL.selectInto(
				"SELECT ArticleID, SUM(IFNULL(Amount,0)), SUM(IFNULL(ArticlePiecesPerBunch,0)*IFNULL(Amount,0)) FROM OrdersDetails  "
						+ " WHERE OrderID IN (:{orderIDs}) GROUP BY ArticleID ORDER BY ArticleID "
						+ " INTO :article, :amount, :pieces",
				sums, new NVPair("orderIDs", orderIDs));



Where orderIDs is an ArrayList with selected Orders. When I invoke this SQL statements I get the orders that way (just printed ArticleID for brevity):

1023
1016
1046
2025
2085
2025
2185
3045
3095
3505


As you can see the article number "2025" is printed more than once, although it should be grouped together.

When I take the exact same SQL statement, paste it to MySQLWorkbench
SELECT ArticleID, SUM(IFNULL(Amount,0)), SUM(IFNULL(ArticlePiecesPerBunch,0)*IFNULL(Amount,0)) FROM BFZ.OrdersDetails WHERE OrderID IN (30, 27, 17) GROUP BY ArticleID ORDER BY ArticleID;

and then invoke it, I get this result
1016
1023
1046
2025
2085
2185
3045
3095
3505


As you can see its sorted and grouped correctly.

So I assume the statement processor of Scout is invoking the statement for every OrderID on its own (in this case 3 times) and then a List with the result of the 3 separate queries is returned.

Is there a way to make the SQL statement work as expected or do I have to manually group the result in code (which is very cumbersome).

Can any one prove or disprove my assumption?

Thanks,

Peter
Re: SQL.selectInto(...) with IN clause and Grouping [message #1728507 is a reply to message #1728481] Tue, 05 April 2016 02:12 Go to previous messageGo to next message
Eclipse UserFriend
Yes the SQL layer is sometime complicated with for those list/batch cases. You can read the Javadoc of "ISqlService" (feel free to report any improvement we can do to this documentation)

Some inputs for your statement:

For the WHERE part:
If "orderIDs" is a Java collection (like a list) or an array I think you can write:
OrderID = :orderIDs

=> At this point you can test your statement with SQL.select(..), by checking if you get the correct data in the Object[][] returned value.

For the INTO part:
I am not sure to follow the type of your output binds: ":article" ":amount" and ":pieces". Is sum a BeanArrayHolder or just a simple POJO bean or a FormData?

-------------------------
Related topics:
* BeanArrayHolder and FormData
* SQL.update(...) with IN clause
Re: SQL.selectInto(...) with IN clause and Grouping [message #1728527 is a reply to message #1728507] Tue, 05 April 2016 03:41 Go to previous messageGo to next message
Eclipse UserFriend
Hi Jeremie,

thanks for the quick reply.

I used both ways
OrderID = :orderIDs


and

OrderID IN (:orderIDs)


But it was the same result.

Yes, sums is just a BeanArrayHolder, because when I directly use the table from the formdata only the result of the last query gets added to the table... The first two resultsets are thrown away... But I don't know why.

I will test the SQL.select() method and come back to you.

Regarding improvements: I would expect, the SQLService is capable of commons SQL statements...

Thanks

Peter
Re: SQL.selectInto(...) with IN clause and Grouping [message #1728557 is a reply to message #1728527] Tue, 05 April 2016 08:33 Go to previous messageGo to next message
Eclipse UserFriend
Hi Jeremie,

it tried the Object[][] SQL.select(..) method. The result is unfortunately the same.

It seems that the SQL Statement is invoked once per entry in the ArrayList... Which is not the way, the SELECT statement with grouping is expected to work Sad

How are you dealing with grouping in your projects, since it's common practice though, I think?

Peter
Re: SQL.selectInto(...) with IN clause and Grouping [message #1728705 is a reply to message #1728557] Wed, 06 April 2016 10:29 Go to previous messageGo to next message
Eclipse UserFriend
Dear Peter,

I just tried it out. It works, if I use a LongArrayHolder to store the numbers (the order numbers in your case) instead of an ArrayList.

I.e. the statement is indeed executed once per entry in the ArrayList if you directly use an ArrayList as bind variable.

Cheers, Samuel
Re: SQL.selectInto(...) with IN clause and Grouping [message #1728723 is a reply to message #1728557] Wed, 06 April 2016 12:51 Go to previous message
Eclipse UserFriend
I also did some tests on my side, using the PERSON table from the Contacts Demo application. (Derby Database):

Input Data:
+------------+------------+----------------+---------+
| first_name | last_name  |      city      | country |
+------------+------------+----------------+---------+
| Anna       | Mills      | Arlington      | US      |
| Melody     | Bergnaum   | Portland       | US      |
| Bart       | Zulauf     | Arlington      | US      |
| Wilmer     | Fay        | Virginia Beach | US      |
| Axel       | Hahn       | Chandler       | US      |
| Hermina    | Borer      | Birmingham     | GB      |
| Peter      | Crist      | Portland       | US      |
| Daisha     | Rohan      | London         | GB      |
| Lonnie     | Marks      | London         | GB      |
| Evert      | Johnson    | Birmingham     | GB      |
| Holly      | Beier      | London         | GB      |
| Grant      | Reichel    | London         | GB      |
| Xander     | Spinka     | Portland       | US      |
| Cara       | Turcotte   | Virginia Beach | US      |
| Jade       | McLaughlin | Portland       | US      |
+------------+------------+----------------+---------+


Statement 1:
Object[][] data = SQL.select("select city, count(1) from PERSON group by city");

The data object array contains the values:
+----------------+---+
| Arlington      | 3 |
| Birmingham     | 2 |
| Chandler       | 2 |
| London         | 6 |
| Portland       | 4 |
| Virginia Beach | 3 |
+----------------+---+


Statement 2:
Object[][] data = SQL.select("select city, count(1) from PERSON where country in ('GB', 'US') group by city"); 

Same result as for statement 1.

Statement 3:
Object[][] data = SQL.select("select city, count(1) from PERSON where country in ('GB') group by city"); 

The data object array contains the values:
+------------+---+
| Birmingham | 2 |
| London     | 6 |
+------------+---+


Statement 4:
    List<String> countries = Arrays.asList("GB", "US");
    Object[][] data = SQL.select("select city, count(1) from PERSON where country=:c group by city", new NVPair("c", countries));

Same result as for statement 1.

Statement 5:
    List<String> countries = Arrays.asList("GB");
    Object[][] data = SQL.select("select city, count(1) from PERSON where country=:c group by city", new NVPair("c", countries));

Same result as for statement 3.

Statement 6:
    List<String> countries = Collections.emptyList();
    Object[][] data = SQL.select("select city, count(1) from PERSON where country=:c group by city", new NVPair("c", countries)); 

The data object array is an empty array (data.length == 0):

It works exactly as expected.

-------------------

Now for the SelectInto part: you need to provide a Java Structure that is a compatible "batch INTO bind" (referring to the JavaDoc of ISqlService). If you have one of those, "For every row in the select, one row is created and filled up".

=> java.util.List is not one of those. The reason is simple: there in not enough information (do not forget the java type erasure of the generics parameter). The SqlService, needs to know how to create a new list element for each row in the SQL result set.

You can use:
* XxxxArrayHolder (like LongArrayHolder as told by Samuel)
* In particular BeanArrayHolder (see my example below)
* If you are working with FormData, the your TableFieldBeanData classes (or TableFieldData classes) corresponding to the table-fields of your form.
* PageData classes.

Example 1:
    List<String> countries = Arrays.asList("GB", "US");
    BeanArrayHolder<PersonInCityPojo> data = new BeanArrayHolder<PersonInCityPojo>(PersonInCityPojo.class);
    SQL.selectInto("select city, count(1) from PERSON where country=:c group by city INTO :result.cityName, :result.personCount", new NVPair("c", countries), new NVPair("result", data));
    //Continue with data.getBeans() and/or data.getBeanCount()

... and you will get the expected result.

Where PersonInCityPojo is a simple java bean (or POJO):
public class PersonInCityPojo {
  private String cityName;
  private int personCount;

  public String getCityName() {
    return cityName;
  }

  public void setCityName(String cityName) {
    this.cityName = cityName;
  }

  public int getPersonCount() {
    return personCount;
  }

  public void setPersonCount(int personCount) {
    this.personCount = personCount;
  }
} 


Using curly brackets in the Input-Binds is not a good idea. Quoting the JavaDoc of ISqlService:
Quote:
Input Binds:
(...) :{name} is a batch value. For every value in the array the statement is executed once.

=> I think that you can use this construct for insert statements.

Again, I know that the documentation of the SQL Service is far from perfect. Feel free to contribute improvements (or ideas).
Previous Topic:Where does the @TunnelToServer annotation belong to?
Next Topic:[neon] Code completion broken with SDK M6_1
Goto Forum:
  


Current Time: Sun Aug 31 17:54:50 EDT 2025

Powered by FUDForum. Page generated in 0.04082 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top