DB2 syntax when running H2 (in DB2 mode) - db2

I have the following query which works nice when running directly against DB2:
String sql =
"select slutt_dato + 1 day as tDato from klv80201 " +
"union " +
"select fra_dato as tDato from klv12101 where avtalenr = :avtalenr and kundenr = :kundenr " +
"union " +
"select fra_dato as tDato from klv12401 where avtalenr = :avtalenr and kundenr = :kundenr and MEDLEMSTATU < '32' " +
"order by tDato desc fetch first 1 rows only;";
But when I run it through a test with H2 as database with the following configuration:
jdbc:h2:mem:play;MODE=DB2;LOCK_TIMEOUT=10000;LOCK_MODE=0
I get the following error message:
org.h2.jdbc.JdbcSQLException: Column "SLUTT_DATO" not found; SQL
statement: select slutt_dato + 1 day as tDato from klv80201 union
select fra_dato as tDato from klv12101 where avtalenr = ? and kundenr
= ? union select fra_dato as tDato from klv12401 where avtalenr = ? and kundenr = ? and MEDLEMSTATU < '32' order by tDato desc fetch first
1 rows only; [42122-149]
If I remove the "+1 day" the query works nice in H2. The error message from the H2 JDBC driver is wrong, column "SLUTT_DATO" does exist and works nice when removing "+1 day".
Any good suggestions why H2 acts like it does? Is it a bug or is it me that misunderstands something?
Thanks in advance

H2 doesn't understand + 1 day and gets confused here. This will work however:
"select slutt_dato + 1 as tDato from klv80201 "
But I'm afraid this will no work for IBM DB2... I don't think there is an easy solution to this problem that works on both IBM DB2 and H2.

Related

Sql column alias not working in Ebeans rawsql

I am facing strange issue with raw SQLs, and I need some help to figure out the best way to fix it. I could, of course, add the columnMappings, but I want to make sure it's not because I am doing something wrong.
Play Framework APP
Ebeans ORM
Postgresql 9.,4
Executing the following RawSQL against a Postgresql database fails if I don't define columnMappings, although I have an alias defined:
String sql
= " Select date_trunc('day', end_time) as theDate, "
+ " count(*) as value "
+ " From ebay_item "
+ " group by date_trunc('day', end_time) ";
RawSql rawSql =
RawSqlBuilder
.parse(sql)
.create();
Error:
016-03-25 12:05:15,303 ERROR m.c.a.e.s.p.SimpleDBPromiseService - Error executing named query
javax.persistence.PersistenceException: Property [dateTrunc('day'] not found on models.com.abiesolano.ebay.sqlpojos.RangedDateCounter
If I switch to an H2 database:
String sql
= " SELECT trunc(end_time) as theDate, "
+ " count(*) as value "
+ " From ebay_item "
+ " Group by trunc(end_time)";
RawSql rawSql =
RawSqlBuilder
.parse(sql)
.create();
it works no problems.
Any suggestion would be really appreciated.
I don't think mysql likes to group or order by functions, you should use your alias "theDate" instead.
Note that if you're mapping to a bean object, the alias must be a #Transient property of your bean to be mapped by Ebean (otherwise, you'll get an unknown property error).

ADO.NET working with SQL and database

I'm getting an exception error saying missing operators can anyone help
string sql = "Select SalesPerson.Name, Item.Description, Orders.Quantity, Orders.OrderDate"
+ "From([Orders]"
+ "Inner Join[SalesPerson] On Orders.SalesPersonID=SalesPerson.SalesPersonID)"
+ "Inner Join[Item] On Orders.ItemNumber=Item.ItemNumber"
+ "Where Orders.CustomerID=#customer Order by Orders.OrderDate DESC";
You need to add some spaces at the end of each of your lines of SQL!
string sql = "SELECT SalesPerson.Name, Item.Description, Orders.Quantity, Orders.OrderDate "
+ "FROM [Orders] "
+ "INNER JOIN [SalesPerson] ON Orders.SalesPersonID = SalesPerson.SalesPersonID "
+ "INNER JOIN [Item] ON Orders.ItemNumber = Item.ItemNumber "
+ "WHERE Orders.CustomerID = #customer "
+ "ORDER BY Orders.OrderDate DESC";
Otherwise, your SQL ends up being
Select ..... Orders.OrderDateFROM([Orders]Inner Join[SalesPerson] .....
and so on - and that's just not valid SQL.
I also removed some unnecessary parenthesis around the JOIN operators - those are only needed for MS Access, but since you're saying you're using ADO.NET, I assume this is not for MS Access and therefore, those parenthesis are not needed

How to execute raw query in JPA?

I'm trying to execute a raw query like this:
em.createNativeQuery(
"WITH RECURSIVE recursetree(id, parent_id) AS (\n" +
"SELECT id, parent_g_id FROM group WHERE parent_g_id = 2\n" +
"UNION\n" +
" SELECT t.id, t.parent_g_id\n" +
" FROM group t\n" +
" JOIN recursetree rt ON rt.id = t.parent_g_id\n" +
" )\n" +
"SELECT * FROM recursetree;").getResultList();
On the Postgres side (via PGAdmin) it works fine, but from Java it get the following error:
java.lang.IllegalArgumentException: argument type mismatch
What do I do wrong? How to execute a really raw query on Postgres from a Java EE environment?

JPQL "DISTINCT" returns only one result

I am confused by DISTINCT in JPQL. I have two JPQL queries identical except for "DISTINCT" in one of them:
String getObjectsForFlow =
"SELECT " +
" se.componentID " +
"FROM " +
" StatisticsEvent se " +
"WHERE " +
" se.serverID IS NOT NULL " +
" AND se.flowID = :uuid " +
" AND se.componentID IS NOT NULL " +
"ORDER BY " +
" se.timeStamp desc ";
String getObjectsForFlowDistinct =
"SELECT DISTINCT " +
" se.componentID " +
"FROM " +
" StatisticsEvent se " +
"WHERE " +
" se.serverID IS NOT NULL " +
" AND se.flowID = :uuid " +
" AND se.componentID IS NOT NULL " +
"ORDER BY " +
" se.timeStamp desc ";
I run a little code to get the results from each query and dump them to stdout, and I get many rows with some duplicates for non-distinct, but for distinct I get only one row which is part of the non-distinct list.
NOT DISTINCT
::: 01e2e915-35c1-6cf0-9d0e-14109fdb7235
::: 01e2e915-35c1-6cf0-9d0e-14109fdb7235
::: 01e2e915-35d9-afe0-9d0e-14109fdb7235
::: 01e2e915-35d9-afe0-9d0e-14109fdb7235
::: 01e2e915-35bd-c370-9d0e-14109fdb7235
::: 01e2e915-35bd-c370-9d0e-14109fdb7235
::: 01e2e915-35aa-1460-9d0e-14109fdb7235
::: 01e2e915-35d1-2460-9d0e-14109fdb7235
::: 01e2e915-35e1-7810-9d0e-14109fdb7235
::: 01e2e915-35e1-7810-9d0e-14109fdb7235
::: 01e2e915-35d0-12f0-9d0e-14109fdb7235
::: 01e2e915-35b0-cb20-9d0e-14109fdb7235
::: 01e2e915-35a8-66b0-9d0e-14109fdb7235
::: 01e2e915-35a8-66b0-9d0e-14109fdb7235
::: 01e2e915-35e2-6270-9d0e-14109fdb7235
::: 01e2e915-357f-33d0-9d0e-14109fdb7235
DISTINCT
::: 01e2e915-35e2-6270-9d0e-14109fdb7235
Where are the other entries? I would expect a DISTINCT list containing eleven (I think) entries.
Double check equals() method on your StatisticsEvent entity class. Maybe those semantically different values returns same when equals() is called hence producing this behavior
The problem was the "ORDER BY se.timeStamp" clause. To fulfill the request, JPQL added the ORDER BY field to the SELECT DISTINCT clause.
This is like a border case in the interplay between JPQL and SQL. The JPQL syntax clearly applies the DISTINCT modifier only to se.componentID, but when translated into SQL the ORDER BY field gets inserted.
I am surprised that the ORDER BY field had to be selected at all. Some databases can return a data set ORDERed by a field not in the SELECTion. Oracle can do so. My underlying database is Derby -- could this be a limitation in Derby?
Oracle does not support SELECT DISTINCT with an order by unless the order by columns are in the SELECT. Not sure if any databases do. It will work in Oracle if the DISTINCT is not required (does not run because rows are unique), but if it needs to run you will get an error.
You will get, "ORA-01791: not a SELECTed expression"
If you are using EclipseLink this functionality is controlled by the DatabasPlatform method,
shouldSelectDistinctIncludeOrderBy()
You can extend your platform to return false if your database does not require this.
Still, I don't see how adding the TIMESTAMP will change the query results?
Both queries are incorrect JPQL queries, because ORDER BY clause refers to the item that is not on select list. JPA 2.0 specification contains example that matches to this case:
The following two queries are not legal because the orderby_item is
not reflected in the SELECT clause of the query.
SELECT p.product_name
FROM Order o JOIN o.lineItems l JOIN l.product p JOIN o.customer c
WHERE c.lastname = ‘Smith’ AND c.firstname = ‘John’
ORDER BY p.price
SELECT p.product_name
FROM Order o, IN(o.lineItems) l JOIN o.customer c
WHERE c.lastname = ‘Smith’ AND c.firstname = ‘John’
ORDER BY
o.quantity
Of course it would be nicer if if implementation could give clear error message instead of trying to guess what is expected result of incorrect query.

TSQL Summary by account, what is the cleanest way to approach this?

I am trying to total by account, the expenses & income per account. There are multiples of both the income & the expenses per account. I am struggling with this as am still learning SQL and thought that someone else likely has already addressed this? I sure would appreciate the help!
I know that this SQL server code is not correct but it at least gives a bit clearer picture of what I am attempting to do.
IF(SELECT(OBJECT_ID('TEMPDB..#Total'))) IS NOT NULL DROP TABLE #Total
declare #Expenses decimal(13,2),
#income decimal(13,2)
set #expenses = sum(EXP_CHILD_CARE_AMOUNT)
+ sum(EXP_FOOD_AMOUNT)
+ sum(EXP_LIFE_INSURANCE_AMOUNT)
+ sum(EXP_TRANSPORTATION_AMOUNT)
+ sum(EXP_TUITION_AMOUNT)
+ sum(EXP_USER_2_AMOUNT)
+ sum(EXP_USER_3_AMOUNT)
+ sum(EXP_UTILITIES_AMOUNT)
set #income = (sum(NET_PAY_AMOUNT)
+ sum(OTHER_INCOME_AMOUNT)
SELECT F.LOAN_NUMBER, #Income, #Expenses
INTO #Total
FROM OPENQUERY(SvrLink, '
SELECT F.Account, #Income, #Expenses
FROM finances F
inner join account a on(a.Account = f.Account)
where a.balance > 0
FETCH ONLY WITH UR ')
...ok, assuming that some fields are grouped into the same table (if not you'll just have to write the joins), you just need 1 query. (I wish all languages were as concise...)
#AccountId is your desired account id.
SELECT l.LOAN_NUMBER, l.AccountId,
(SELECT sum(EXP_CHILD_CARE_AMOUNT) + sum(EXP_FOOD_AMOUNT) +
sum(EXP_LIFE_INSURANCE_AMOUNT) + sum(EXP_TRANSPORTATION_AMOUNT) +
sum(EXP_TUITION_AMOUNT) + sum(EXP_USER_2_AMOUNT) +
sum(EXP_USER_3_AMOUNT) + sum(EXP_UTILITIES_AMOUNT)
as ExpenseTotal FROM Expenses_Guessing_The_Table_Name
WHERE AccountId = #AccountId) as ExpenseTotal,
(SELECT sum(NET_PAY_AMOUNT) + sum(OTHER_INCOME_AMOUNT) as IncomeTotal
FROM Income_Guessing_The_Table_Name
WHERE AccountId = #AccountId) as IncomeTotal
FROM Loans l
WHERE l.AccountId = #AccountId AND l.Balance > 0