select data from last 2 rows sql - java

Im using an odbc-jdbc bridge in my project and I need select 2 pieces of data from the database and save the data to 2 variables on the java side of my application. Here is an example of my table.
SITE_ID ------- DEV_ID ------- SCHEDULE_TIME ------- VALUE_ENUM ------- IDX
---------------------------------------------------------------------------
1 3000 09:30:00 1 1
1 3000 11:30:00 0 2
1 3000 12:00:00 1 3
1 3000 14:00:00 0 4
1 3000 18:30:00 1 5
1 3000 20:30:00 0 6
1 4000 05:00:00 1 1
1 4000 13:30:00 0 2
1 4000 16:30:00 1 3
1 4000 18:30:00 0 4
What I want to do is select SCHEDULE_TIME for the last 2 IDX's where DEV_ID is 3000, so I would like to save 18:30:00 and 20:30:00 in a variables, some examples of statements Ive tried are:
select SCHEDULE_TIME from ARRAY_BAC_SCH_Schedule order by IDX desc limit 1 where DEV_ID = 3000
select SCHEDULE_TIME from ARRAY_BAC_SCH_Schedule order by IDX desc limit (1,1) where DEV_ID = 3000
SELECT TOP 1 SCHEDULE_TIME FROM ARRAY_BAC_SCH_Schedule WHERE DEV_ID = 3000 ORDER BY IDX DESC
Right now Im just worrying about how to get the select statement to work in Query tool before I implement it in the java side. Thanks, Beef.

For SQL Server you should use
SELECT TOP 2 SCHEDULE_TIME from (select SCHEDULE_TIME FROM ARRAY_BAC_SCH_Schedule WHERE DEV_ID = 3000 ORDER BY IDX DESC) as inner
like Hemal told you.
Be careful with queries like
select TOP 2 SCHEDULE_TIME FROM ARRAY_BAC_SCH_Schedule WHERE DEV_ID = 3000 ORDER BY IDX DESC
because that is wrong. SQL Server does the top and then the order.
In PostgreSQL or MySQL you should use limit and the end of the query. The limit is after the where part.
In Oracle you should use rownum inside the where part.

Maybe I'm missing something. Is there a reason you wouldn't just run:
select SCHEDULE_TIME from ARRAY_BAC_SCH_Schedule order by IDX desc limit 2 where DEV_ID = 3000
This should return 2 rows, containing 20:30:00 and 18:30:00.

if it is mysql then
select SCHEDULE_TIME from ARRAY_BAC_SCH_Schedule where DEV_ID = 3000 order by IDX desc limit 2

I think
SELECT TOP 2 * from (select SCHEDULE_TIME FROM ARRAY_BAC_SCH_Schedule WHERE DEV_ID = 3000 ORDER BY IDX DESC) as inner

The specifics will vary a little based on your DB, but your query should look something like this:
SELECT TOP 2 SCHEDULE_TIME
FROM ARRAY_BAC_SCH_Schedule
WHERE DEV_ID = 3000
ORDER BY IDX Desc
Or, on one line:
SELECT TOP 2 SCHEDULE_TIME FROM ARRAY_BAC_SCH_Schedule WHERE DEV_ID = 3000 ORDER BY IDX Desc

You can do that with subquerys:
select * from array_bac_sch_schedule where (value_enum,idx) in (select value_enum,idx from array_bac_sch_schedule where dev_id=3000) order by schedule_time desc limit 2;
I took value_enum and idx as primary key.

Related

Remove duplicate records from child table and update parent with newly inserted child records reference id for billions of records

Employee has multiple versions of addresses and given addresses are being duplicate needs to be removed and replaced with single unique address row and update parent table with newly inserted address id reference in optimal way .
CREATE TABLE address (adr_id, ver_id, address) AS
SELECT 1, 1, 'newYork' FROM DUAL UNION ALL
SELECT 1, 2, 'newYork' FROM DUAL UNION ALL
SELECT 1, 3, 'newYork' FROM DUAL UNION ALL
SELECT 4, 1, 'Washington' FROM DUAL UNION ALL
SELECT 4, 2, 'Washington' FROM DUAL;
CREATE TABLE employee (emp_id,adr_id,ver_id,) AS
SELECT 100,1, 1 FROM DUAL UNION ALL
SELECT 200,1, 2 FROM DUAL UNION ALL
SELECT 300,1, 3 FROM DUAL UNION ALL
SELECT 400,4, 1 FROM DUAL UNION ALL
SELECT 500,4, 2 FROM DUAL;
Before
employee
id | adr_id | ver_id
100 1 1
200 1 2
300 1 3
400 4 1
500 4 2
Address
adr_id | ver_id | address
1 1 newYork
1 2 newYork
1 3 newYork
4 1 Washington
4 2 Washington
Expected After
Address
adr_id | ver_id | address
11 0 newYork
12 0 Washington
employee
id | adr_id | ver_id
100 11 1
200 11 2
300 11 3
400 12 1
500 12 2
Note: There is foreign key constraint between Employee and Address table with composite key comprising of adr_id & ver_id
This is being done using stored procedure but its too slow is there any parallel processing can be done here by some way?

Select from table and keep all lines with a certain column value in the bottom of the result

I have the following table:
name
age
pedro
11
duda
12
joao
7
pedro
9
guga
10
pedro
13
zelda
10
What I want is to select all entries here in which age >= 10, but at the same time keep all results which name = pedro in the last position, like this:
name
age
duda
12
guga
10
zelda
10
pedro
11
pedro
13
So there are two questions:
is it possible to do it with a select statement?
if so, is it possible to do this with JPA Repository simply naming a method?
is it possible to do it with a select statement?
Yes you can use where and order by with case like:
select *
from table
where age >= 10
order by case name when 'pedro' then 2 else 1 end
You can use CASE WHEN in the ORDER BY
SELECt * FROM tab1
WHERE age >= 10
ORDER BY CASE WHEN `name` = 'Pedro' THen 2 ELSE 1 END ASC, `name` ASC, `age` ASC
name | age
:---- | --:
duda | 12
guga | 10
zelda | 10
pedro | 11
pedro | 13
db<>fiddle here

Oracle order by via JPA with numeric first

I have column data like this in my db
data
-----
1
2
A
3
4
B
I have below nls settings in place
SELECT * From NLS_SESSION_PARAMETERS;
NLS_LANGUAGE AMERICAN
NLS_TERRITORY AMERICA
NLS_CURRENCY $
NLS_ISO_CURRENCY AMERICA
NLS_ISO_CURRENCY AMERICA
NLS_NUMERIC_CHARACTERS .,
NLS_CALENDAR GREGORIAN
NLS_DATE_FORMAT DD-MON-RR
NLS_DATE_LANGUAGE AMERICAN
NLS_SORT BINARY
NLS_COMP BINARY
When I query the db for **select data from <mytable> order by data ** I am getting the result as below
data
-----
1
2
3
4
A
B
The same query via hibernate is giving the results with alphabets first and numeric later
data
-----
A
B
1
2
3
4
But, I want column to be displayed with numbers first and alphabets later via hibernate
data
------
1
2
3
4
A
B
Can someone help me with this.
You can use regularexpressions to sort in such a way,
select data from <mytable> order by REGEXP_REPLACE(data ,'[^0-9]'), REGEXP_REPLACE(data ,'[0-9]')
That depends on NLS_SORT parameter's value. For example, in my database it is set to CROATIAN and the result is what you wanted:
SQL> select * From nls_session_parameters where parameter = 'NLS_SORT';
PARAMETER VALUE
-------------------- --------------------
NLS_SORT CROATIAN
SQL> with test (data) as
2 (select '1' from dual union all
3 select '2' from dual union all
4 select 'A' from dual union all
5 select '3' from dual union all
6 select '4' from dual union all
7 select 'B' from dual
8 )
9 select data
10 from test
11 order by data;
D
-
A
B
1
2
3
4
6 rows selected.
However, in your database, NLS_SORT = BINARY. Let's try it:
SQL> alter session set nls_sort = 'BINARY';
Session altered.
SQL> with test (data) as
2 (select '1' from dual union all
3 select '2' from dual union all
4 select 'A' from dual union all
5 select '3' from dual union all
6 select '4' from dual union all
7 select 'B' from dual
8 )
9 select data
10 from test
11 order by data;
D
-
1
2
3
4
A
B
6 rows selected.
SQL>
Right; the wrong result.
Therefore, modify NLS_SORT, if that's an option. See valid values by
SQL> select * From v$nls_valid_values where parameter = 'SORT';
PARAMETER VALUE ISDEP
-------------------- -------------------- -----
SORT BINARY FALSE
SORT WEST_EUROPEAN FALSE
SORT XWEST_EUROPEAN FALSE
SORT GERMAN FALSE
<snip>
I believe one of the two options below should work,
Use NLSSORT function in the order by clause explicitly.
select * from my_table order by NLSSORT(data,'NLS_SORT=BINARY');
Create a function based index on the column,
create index mytable_nlssort_index on my_table(nlssort(data, 'nls_sort=''BINARY'''))
Use the query as below when the column is indexed.
select data from my_table order by data;

Symptoms and its disease database design

Im working with android health application which will display human body parts such as head, chest etc.. For now I have three tables such as symptoms, diseases and symptom_disease table which will link those two table. If user select symptom such as dizziness, syncope, asthenia and others, then it will display hypertensive disease. But it will have problem when user select only one symptoms let say dizziness, it will also display the same disease. How do i differentiate this things? and how to implement it.
This is my symptom table
s_id | s_name | s_part
1 |dizziness | Head
2 |syncope | Head
3 |asthenia | Head
Disease table
d_id | d_name | d_desc
1 |hypertensive disease| ....
Symptom_disease table
s_id | d_id
1 | 1
2 | 1
3 | 1
I use this query to get the disease
SELECT d.d_name, d.d_desc, s.symp_name
FROM symtoms s
LEFT JOIN symptom_disease sd ON sd.sid = s.sid
LEFT JOIN diseases d ON d.did = sd.did
WHERE s.sid IN (1,2,3) GROUP BY d.d_name
The problem here is when user select only one disease, I dont want it show the disease because one symptoms does not show that the user is ill. So, I need a suggestion on how to implement this. I have see a solution which require me to add rank/weight inside symptom_disease table. But I dont know how to implement this method. Thanks in advance.
Here's a basic approach to use something like a probability column to determine the likelihood of a particular disease.
For diseases table:
1 Flu
2 Lyme
For symptoms table:
1 Muscle Aches
2 Headache
3 Fatigue
4 Fever
5 Vomiting
6 Tick Bite
For disease_symptom table:
s_id d_id probability
1 1 0.2
2 1 0.2
3 1 0.2
4 1 0.2
5 1 0.2
1 2 0.1
2 2 0.1
3 2 0.1
4 2 0.1
6 2 0.6
So if a patient says that have symptoms 2, 4, and 5, then
select d_name, sum(probability)
from disease, disease_symptom
where disease.d_id = disease_symptom.d_id
and s_id in (2, 4, 5)
group by d_name
order by sum(probability) desc
is
Flu 0.6
Lyme 0.2
so Flu is the most likely.
But if the patient has symptoms 2, 4, and 6, then
select d_name, sum(probability)
from disease, disease_symptom
where disease.d_id = disease_symptom.d_id
and s_id in (2, 4, 6)
group by d_name
order by sum(probability) desc
is
Lyme 0.8
Flue 0.4
so Lyme disease is mostly likely.
This may not be the most elegant way of doing it, but it should work, assuming you're using MySql:
select *
from
(
select d.d_name, d.d_desc, GROUP_CONCAT(sd.s_id SEPARATOR ',') s_ids
from Diseases d , Symptom_disease sd
where sd.d_id = d.d_id
group by d.d_name, d.d_desc
order by sd.s_id
) as t
where t.s_ids = '1,2,3'
;
You need to make sure you concatenate all the sympton ids in ascending order in the where clause of the outer select ( where t.s_ids = '1,2,3'), and it should give you only the diseases whose symptons match exactly the ones your users selected.

Select single row for column value

Here is sample table data which is dynamic.
ColId Name JobId Instance
1 aaaaaaaaa 1 2dc757b
2 bbbbbbbbb 1 2dc757b
3 aaaaaaaaa 1 010dbb8
4 bbbbbbbbb 1 010dbb8
5 bbbbbbbbb 1 faa2733
6 aaaaaaaaa 1 faa2733
7 aaaaaaaaa 1 bc13d69
8 aaaaaaaaa 1 9428f4d
I want output like
ColId Name JobId Instance
1 aaaaaaaaa 1 2dc757b
3 aaaaaaaaa 1 010dbb8
5 bbbbbbbbb 1 faa2733
7 aaaaaaaaa 1 bc13d69
8 aaaaaaaaa 1 9428f4d
What should be the JPA query so that I can retrieve entire row having only single 'Instance'(there is no max min condition involved).
I need one row for each 'Instance' value
FROM table t GROUP BY t.instance should suit your needs.
Something like JPQL "Select entity from Entity entity where entity.id in (select min(subinstance.id) from Entity subinstance group by subinstance.instance)"
Functions like count, min, avg etc are allowed over columns not included in the group by statement, so any such should work if it returns a single id value from the grouping.

Categories