jpa native query, select same table twice problems (hibernate implementation) - mysql

There is a requirement which i should use the jpa native query (because jpa doesn't support timestampdiff function).
Also i should select same table twice, such as:
I have table: Individual, Task, and etc
The native query i used is: “select emp.name, tsk.name, app.name, from Individual emp, Task tsk, Individual app where ................”
The expected data i want is: "Tom, task1, Jack", however the result data is "Jack, task1, Jack" given this native sql query. Which means the app.name overrides emp.name.
If i want to get the correct result i have to use the query like: "select emp.name, tsk.name, (select app.name from Individual app where xx.id=xx.id), from Individual emp, Task tsk, Individual app where ................"
code for native query (get wrong data):
String nativeSql = "select con.first_name, app.first_name from Individual con, Task tsk, TimeBlock tb, Timesheet ts, Individual app where con.id=ts.owner_id and tb.timesheet_id=ts.id and tb.task_id=tsk.id and tsk.approver_id=app.id";
Query query = entityManager.createNativeQuery(nativeSql);
code for native query (can get correct data):
String nativeSql = "select con.first_name, (select app.first_name from Individual app where tsk.approver_id=app.id) from Individual con, Task tsk, TimeBlock tb, Timesheet ts, Individual app where con.id=ts.owner_id and tb.timesheet_id=ts.id and tb.task_id=tsk.id and tsk.approver_id=app.id";
Query query = entityManager.createNativeQuery(nativeSql);
code for jpql query:
String jpql = "select con.firstName, app.firstName from Individual con, Task tsk, TimeBlock tb, Timesheet ts, Individual app where con.id=ts.owner.id and tb.timesheet.id=ts.id and tb.task.id=tsk.id and tsk.approver.id=app.id";
Query query = entityManager.createQuery(jpql);
But the interesting is:
I used this native sql query to search from mysql db (using command line, workbench whatever), the result data is the correct one "Tom, task1, Jack"
If i used the jpql for this requirement without timestampdiff feature, the result data is also the correct one.
Just tried the jdbc, if i used the native sql query in jdbc, I can also get the correct data.
It seems some problem for jpa....
So anyone who met this kind of problem before and know the essential of that.
Thanks for your help.

Got the same problem, just found out that you got to alias the columns to fix the problem.
This gave me wrong result :
SELECT i.number, taux5_50.vatAmount, taux19_60.vatAmount
FROM Invoice i
LEFT JOIN InvoiceVATLine taux5_50 ON taux5_50.invoice_id=i.id AND taux5_50.rate=5.50
LEFT JOIN InvoiceVATLine taux19_60 ON taux19_60.invoice_id=i.id AND taux19_60.rate=19.60
WHERE ...
This gave me correct result :
SELECT i.number, taux5_50.vatAmount AS taux5_50_vatAmount, taux19_60.vatAmount AS taux19_60_vatAmount
FROM Invoice i
LEFT JOIN InvoiceVATLine taux5_50 ON taux5_50.invoice_id=i.id AND taux5_50.rate=5.50
LEFT JOIN InvoiceVATLine taux19_60 ON taux19_60.invoice_id=i.id AND taux19_60.rate=19.60
WHERE ...

Related

Subquery from different data source (Eclipse report)

My requirement is to have a query that is something like the following:
SELECT * FROM table1
WHERE oid in (
SELECT * FROM table 2
WHERE condition )
My problem is that table1 and table2 are on different databases.
I've read around that you can do something like [db1].table but it doesn't work in my case using Eclipse Birt enviroment.
You can solve this in two ways:
1) Use something like a database link. There is limited support in MySQL (note: I've hardly ever used MySQL) See Oracle Database Link - MySQL Equivalent?. This way, you move the problem to the database level.
2) Depending on the actual problem (read: the length of the "select oid FROM table2 where condition" results, you could use either a BIRT data cube or
3) Use two DataSets and a layout structure list-table like this:
The two DataSets need different DataSources.
DataSet "T2_oids" with a query "select oid from table2 where condition".
DataSet "T1_object" with a single parameter param_oid and a query "select * from table1 where oid = ?".
Layout structure:
* Outer ListItem "T2_oids" bound to DataSet "T2_oids"
* Inner TableItem or ListItem "T1_object" bound to DataSet "T1_object" with the parameter bound to row["oid"] (or row["OID"], use the list box). This item must be placed inside the T2_oids detail section.
Since T1_object will return a single row, you can even use a GridItem instead of a TableItem or ListItem.

Django mysql count distinct gives different result to postgres

I'm trying to count distinct string values for a fitered set of results in a django query against a mysql database versus the same data in a postgres database. However, I'm getting really confusing results.
In the code below, NewOrder represents queries against the same data in a postgres database, and OldOrder is the same data in a MYSQL instance.
( In the old database, completed orders had status=1, in the new DB complete status = 'Complete'. In both the 'email' field is the same )
OldOrder.objects.filter(status=1).count()
6751
NewOrder.objects.filter(status='Complete').count()
6751
OldOrder.objects.filter(status=1).values('email').distinct().count()
3747
NewOrder.objects.filter(status='Complete').values('email').distinct().count()
3825
print NewOrder.objects.filter(status='Complete').values('email').distinct().query
SELECT DISTINCT "order_order"."email" FROM "order_order" WHERE "order_order"."status" = Complete
print OldSale.objects.filter(status=1).values('email').distinct().query
SELECT DISTINCT "order_order"."email" FROM "order_order" WHERE "order_order"."status" = 1
And here is where it gets really bizarre
new_orders = NewOrder.objects.filter(status='Complete').values_list('email', flat=True)
len(set(new_orders))
3825
old_orders = OldOrder.objects.filter(status=1).values_list('email',flat=True)
len(set(old_orders))
3825
Can anyone explain this discrepancy? And possibly point me as to why results would be different between postgres and mysql? My only guess is a character encoding issue, but I'd expect the results of the python set() to also be different?
Sounds like you're probably using a case-insensitive collation in MySQL. There's no equivalent in PostgreSQL; the closest is the citext data type, but usually you just compare lower(...) of strings, or use ILIKE for pattern matching.
I don't know how to say it in Django, but I'd see if the count of the set of distinct lowercased email addresses is the same as the old DB.
According to the Django docs something like this might work:
NewOrder.objects.filter(status='Complete').values(Lower('email')).distinct()

An item with the same key has already been added - SQL Server 2012 Subquery Issue

I am writing code within SQL server 2012 to transfer into the query designer of Report Builder 3.0.
My code works perfect within Management studio, and it works within the actualy query designer, but once I press Okay within the query designer, it throws me the error:
"Could not update a list of fields for the query. Verify that you can connect to the data source and that your query syntax is correct"
Under details:
"An item with the same key has already been added"
This is the code I am using:
Select *
from
(Select distinct srt.Name,
percentile_disc(.5) WITHIN GROUP(ORDER BY (sr.price)) OVER(PARTITION BY srt.Name) AS MedianSpend
from ServiceReq sr inner join ServiceReqTemplate srt
on srt.RecId = sr.SvcReqTmplLink_RecID Where Name like '%') medQuery
inner join
(select distinct srt.Name,
cast(sum(sr.price) as int) as AvgCost,cast(sum(sr.cost) as int) as
AvgTransCost,cast(avg(sr.TotalTimeSpent) as int) as TotalTimeSpent
from ServiceReq sr, ServiceReqTemplate srt
where sr.SvcReqTmplLink_RecID = srt.RecId
group by srt.Name) avgQuery
on medQuery.Name LIKE avgQuery.Name
I think that the problem is there would be two columns both called "Name" in one table, which is not allowed. I was thinking I could add another column in the same table, and call it "Name_2" and then copy and paste all the data from the "Name" table into "Name_2" and then use it. Would this be the easiest way of successfully implementing this code into Report Builder?
You add AS Name2 to the 2nd query and then call it after avgQuery at the end.

CI active record style sql queries

I am new in Code Igniter and like its active record feature now is there any useful steps or tips or any guidness how do i convert my pervoiusly written simple SQL Queries in CI style like this is my perviouly written simple query
SELECT *
FROM hs_albums
WHERE id NOT IN (SELECT album_id
FROM hs_delete_albums
WHERE user_id = 72
AND del_type = 1)
AND ( created = 72
OR club_id IN (SELECT cbs.id
FROM hs_clubs cbs
INNER JOIN hs_club_permissions cbp
ON cbs.id = cbp.club_id
WHERE cbp.user_id = 72
AND cbp.status = 2)
OR group_id IN (SELECT gps.id
FROM hs_groups gps
INNER JOIN hs_group_permissions grp
ON gps.id = grp.group_id
WHERE grp.user_id = 72
AND grp.status = 2)
OR comp_id IN (SELECT cmp.id
FROM hs_companies cmp
INNER JOIN hs_comp_permissions comp
ON cmp.id = comp.comp_id
WHERE comp.user_id = 72
AND comp.status = 2) )
The short answer is: You don't.
CodeIgniter's Active Record implementation is basically a layer on top of SQL that makes writing queries easier by:
Automatically escaping values
Automatically generating the appropriate query syntax for the database, so that the application can be more easily ported between databases (for instance, if you didn't use Active Record to write a query, and then wanted to move from MySQL to PostgreSQL, then you might well need to rewrite the query to make it work with PostgreSQL)
Providing a syntax for queries in PHP directly, thus avoiding the context switching between PHP and SQL.
However, it can't do everything SQL can do, and while I would always try to use ActiveRecord where possible, there comes a point where you're better off forgetting about using it and just using $this->db->query() to write your query directly. In this case, as mamdouh alramadan has said, CodeIgniter doesn't support subqueries so you can't replicate this query using ActiveRecord anyway.
The thing to remember is that ActiveRecord is a tool, not a requirement. If you're using CodeIgniter and aren't using an ORM instead, you should use it for the reasons mentioned above. However, once it starts getting in the way, you should consider whether it would be better practice to write your query manually instead.

When using skip and take to page data, how can I get the total record count without a separate query?

I don't see how this is possible, but I really, really hate to run my query an extra time just to get the record count so I can build a pager. When I say a "pager" I simply mean the common gizmo with a link for each 10 records for example.
Assuming you are building a query in the selecting event, the best you could do is construct the full query, get and save the count, then take or skip it into the e.result.
And by best I mean, the easiest read code from a single query, rather than two. You'll still be running two separate evaluations on the database though. Use query analyser to see if the statements are a 'Select Count' then a 'Select take' or a dirty big select pared down by LINQ after the retrieve. I think LINQ does the former.
As far as I know it is not possible to return the total count and the items retrieved by skip and take at the same time.
I wrote a custom data source control and view, which caches the count for a short duration. I invalidate the cache whenever the criteria changes that would affect the number of results, but not when the data is paged, or when the data is sorted for instance.
I was concerned about this same question. Here is are the results of my experimenting in Linqpad--the actual behavior of Linq does not create a full new query to the SQL server:
This simple test, in one of my development databases:
var query = from p in HrPersons select p;
var x = query.Skip(20).Take(10).Dump();
var t = query.Count().Dump();
generates the following actual SQL queries:
SELECT [t1].[company] AS [Company], [t1].[processLevel] AS [ProcessLevel], [t1].[emplId] AS [EmplId], [t1].[sn] AS [Sn], [t1].[givenName] AS [GivenName], [t1].[middleInitial] AS [MiddleInitial], [t1].[nickName] AS [NickName], [t1].[formerName] AS [FormerName], [t1].[ssn] AS [Ssn], [t1].[cn] AS [Cn], [t1].[costCenter] AS [CostCenter], [t1].[title] AS [Title], [t1].[status] AS [Status], [t1].[batch] AS [Batch], [t1].[rowversion] AS [Rowversion], [t1].[id] AS [Id], [t1].[source] AS [Source]
FROM (
SELECT ROW_NUMBER() OVER (ORDER BY [t0].[company], [t0].[processLevel], [t0].[emplId], [t0].[sn], [t0].[givenName], [t0].[middleInitial], [t0].[nickName], [t0].[formerName], [t0].[ssn], [t0].[cn], [t0].[costCenter], [t0].[title], [t0].[status], [t0].[batch], [t0].[rowversion], [t0].[id], [t0].[source]) AS [ROW_NUMBER], [t0].[company], [t0].[processLevel], [t0].[emplId], [t0].[sn], [t0].[givenName], [t0].[middleInitial], [t0].[nickName], [t0].[formerName], [t0].[ssn], [t0].[cn], [t0].[costCenter], [t0].[title], [t0].[status], [t0].[batch], [t0].[rowversion], [t0].[id], [t0].[source]
FROM [HrPerson] AS [t0]
) AS [t1]
WHERE [t1].[ROW_NUMBER] BETWEEN #p0 + 1 AND #p0 + #p1
ORDER BY [t1].[ROW_NUMBER]
GO
SELECT COUNT(*) AS [value]
FROM [HrPerson] AS [t0]
So while there is a second SQL query, it is a trivial one that only requests the total count. I believe this is reasonable and acceptable as a pattern.