How to convert into JPQL for inline view? - spring-data-jpa

I have a question.
In MySQL, I can query as below, but I can't do that in JPQL because JPA 2.1 is not supported for inline view.
select a2.level from (select level from alarm where sensor_id = 32 order by id desc limit 1) as a2 where a2.level = 'warning';
select * from alarm where sensor_id = 32
I wanna find whether there is latest data which is level = 'warning'.
First solution I'm thinking is that converting into JPQL.
Second solution is writing in native query.
I don't know how to do both of them. Please help me out.
thanks!

Related

AdventureWorks2014 - Create an extract of latest hires based upon Job title

I was wondering if anyone could help.
I am trying to write some code that returns a list of the latest hires based upon Jobtitle using the Adventureworks2012 databse.
So far, I have the following:
SELECT DISTINCT HREDH.BusinessEntityID,
HRE.JobTitle,
hre.HireDate
FROM [HumanResources].[EmployeeDepartmentHistory] HREDH
INNER JOIN HumanResources.Employee HRE ON HREDH.BusinessEntityID = HRE.BusinessEntityID
AND hre.BusinessEntityID = (
SELECT TOP 1 BusinessEntityID
FROM HumanResources.Employee hre2
WHERE hre2.JobTitle = hre.JobTitle
ORDER BY HireDate DESC
)
ORDER BY HRE.JobTitle
This appears to work fine, but I am sure there is a better way to do it (without the use of SELECT DISTINCT at the beginning of the statement)
I am trying my best to learn SQL by myself, so any help from the vast pool of knowledge on here would be greatly appreciated!
Thanks,
This will return all rows from the join of the two tables where the hire date for the job title is equal to the highest date for that job title.
SELECT
HREDH.BusinessEntityID
,HRE.JobTitle
,hre.HireDate
FROM [HumanResources].[EmployeeDepartmentHistory] AS HREDH
JOIN HumanResources.Employee AS HRE
ON HREDH.BusinessEntityID = HRE.BusinessEntityID
WHERE HRE.HireDate = (SELECT MAX(HireDate) FROM HumanResources.Employee AS _HRE WHERE HRE.JobTitle = _HRE.JobTitile)
ORDER BY HRE.JobTitle

Reform a postgreSQL query using one (or more) index - Example

I am a beginner in PostgreSQL and, after understanding very basic things, I want to find out how I can get a better performance (on a query) by using an index (one or more). I have read some documentation, but I would like a specific example so as to "catch" it.
MY EXAMPLE: Let's say I have just a table (MyTable) with three columns (Customer(text), Time(timestamp), Consumption(integer)) and I want to find the customer(s) with the maximum consumption on '2014-07-01 01:00:00'. MY SOLUTION (without index usage):
SELECT Customer FROM MyTable WHERE Time='2013-07-01 02:00:00'
AND Consumption=(SELECT MAX(consumption) FROM MyTable);
----> What would be the exact full code, using - at least one - index for the query-example above ?
The correct query (using a correlated subquery) would be:
SELECT Customer
FROM MyTable
WHERE Time = '2013-07-01 02:00:00' AND
Consumption = (SELECT MAX(t2.consumption) FROM MyTable t2 WHERE t2.Time = '2013-07-01 02:00:00');
The above is very reasonable. An alternative approach if you want exactly one row returned is:
SELECT Customer
FROM MyTable
WHERE Time = '2013-07-01 02:00:00'
ORDER BY Consumption DESC
LIMIT 1;
And the best index is MyTable(Time, Consumption, Customer).

postgreSQL classification limit

I have a requirement that needs to query top 5 news for each type and return to frontend, implemented by JPA.
I've two solutions now,
One is to manually append union SQL by annotation,
Call a service by different parameter type in loop.
in fact what I want is just like SQL as below
select id, title, content
from portal p
where p.type = 'NEWS'
order by create_date
limit 5
union
select id,title,content,
from portal p
where p.type = 'MAG'
order by create_date
limit 5
union...
Solution A need to code many SQL statements in JAVA, while solution B is not efficient as types is more than 10.
Is there any other way to query the data? by annotation or postgreSQL function? I'm new to both JPA & Postgres.
Thanks in advance.
You can do this with a single SQL statement. I'm not sure whether you'll be able to avoid a table scan. You might need to include some more columns, depending most likely on whether you need to sort by them.
select *
from (select
id, title, content,
row_number() over (partition by type order by create_date asc) row_num
from portal
) as numbered_rows
where row_num <= 5;
One advantage of this kind of SQL statement is that it requires no maintenance. It will continue to work correctly no matter how many different types you add.
Think carefully whether you need the first five (order by create_date ASC) or the latest five (order by create_date DESC).

Fetching rows in DB2

I know in DB2 (using version 9.7) I can select the first 10 rows of a table by using this query:
SELECT *
FROM myTable
ORDER BY id
FETCH FIRST 10 ROWS ONLY
But how can I get, for example, rows 11 to 20?
I can't use the primary key or the ID to help me...
Thanks in advance!
Here's a sample query that will get rows from a table contain state names, abbreviations, etc.
SELECT *
FROM (
SELECT stabr, stname, ROW_NUMBER() OVER(ORDER BY stname) AS rownumber
FROM states
WHERE stcnab = 'US'
) AS xxx
WHERE rownumber BETWEEN 11 AND 20 ORDER BY stname
Edit: ORDER BY is necessary to guarantee that the row numbering is consistent
between executions of the query.
You can also use the MYSQL compatibility. You just need to activate the vector compatibility for MYS, and then use Limit and Offset in your queries.
db2set DB2_COMPATIBILITY_VECTOR=MYS
db2stop
db2start
An excellent article written by DB2 experts from IBM https://www.ibm.com/developerworks/mydeveloperworks/blogs/SQLTips4DB2LUW/entry/limit_offset?lang=en
Compatibility vector in InfoCenter http://publib.boulder.ibm.com/infocenter/db2luw/v10r1/topic/com.ibm.db2.luw.apdv.porting.doc/doc/r0052867.html
A blog about this http://victorsergienko.com/db2-supports-limit-and-offset/

Is there a way to find TOP X records with grouped data?

I'm working with a Sybase 12.5 server and I have a table defined as such:
CREATE TABLE SomeTable(
[GroupID] [int] NOT NULL,
[DateStamp] [datetime] NOT NULL,
[SomeName] varchar(100),
PRIMARY KEY CLUSTERED (GroupID,DateStamp)
)
I want to be able to list, per [GroupID], only the latest X records by [DateStamp]. The kicker is X > 1, so plain old MAX() won't cut it. I'm assuming there's a wonderfully nasty way to do this with cursors and what-not, but I'm wondering if there is a simpler way without that stuff.
I know I'm missing something blatantly obvious and I'm gonna kick myself for not getting it, but .... I'm not getting it. Please help.
Is there a way to find TOP X records, but with grouped data?
According to the online manual, Sybase 12.5 supports WINDOW functions and ROW_NUMBER(), though their syntax differs from standard SQL slightly.
Try something like this:
SELECT SP.*
FROM (
SELECT *, ROW_NUMBER() OVER (windowA ORDER BY [DateStamp] DESC) AS RowNum
FROM SomeTable
WINDOW windowA AS (PARTITION BY [GroupID])
) AS SP
WHERE SP.RowNum <= 3
ORDER BY RowNum DESC;
I don't have an instance of Sybase, so I haven't tested this. I'm just synthesizing this example from the doc.
I made a mistake. The doc I was looking at was Sybase SQL Anywhere 11. It seems that Sybase ASA does not support the WINDOW clause at all, even in the most recent version.
Here's another query that could accomplish the same thing. You can use a self-join to match each row of SomeTable to all rows with the same GroupID and a later DateStamp. If there are three or fewer later rows, then we've got one of the top three.
SELECT s1.[GroupID], s1.[Foo], s1.[Bar], s1.[Baz]
FROM SomeTable s1
LEFT OUTER JOIN SomeTable s2
ON s1.[GroupID] = s2.[GroupID] AND s1.[DateStamp] < s2.[DateStamp]
GROUP BY s1.[GroupID], s1.[Foo], s1.[Bar], s1.[Baz]
HAVING COUNT(*) < 3
ORDER BY s1.[DateStamp] DESC;
Note that you must list the same columns in the SELECT list as you list in the GROUP BY clause. Basically, all columns from s1 that you want this query to return.
Here's quite an unscalable way!
SELECT GroupID, DateStamp, SomeName
FROM SomeTable ST1
WHERE X <
(SELECT COUNT(*)
FROM SomeTable ST2
WHERE ST1.GroupID=ST2.GroupID AND ST2.DateStamp > ST1.DateStamp)
Edit Bill's solution is vastly preferable though.