This query gives the desired results when working with Oracle as my back-end.
select field1,
field2
from
(select field1,
field2,
LEAD(field2) over (order by r) name
from
(select rownum r,
field1,
field2
from t3
where field2 = 1
)
)
where v != nvl(name, -1);
But I am facing issues while querying to Interbase database because analytical functions lag() and lead()are not supported in InterBase6.
My requirement is, if array field2={1,3,4,4,3,4}, then I should get results as {1,3,4,3,4}.
I have no idea on interbase but I can give you points to write a query to replicate lead function. You can build on that.
Find a column you want to order the rows by. The rownum you are using in your oracle query is not a correct way to do so. As you cannot guarantee that the results will be displayed in same order all the time. So assuming field1 is the column you want to order by.
Now find a way to generate a sequence number from 1 - n in interbase, based on the order above. where n being your total number of rows. So your sample table might look like below.
+-----+--------+--------+
| seq | field1 | field2 |
+-----+--------+--------+
| 1 | 101 | 1 |
| 2 | 102 | 3 |
| 3 | 103 | 4 |
| 4 | 104 | 4 |
| 5 | 105 | 3 |
+-----+--------+--------+
Once you have achieved the above task, you are almost done. You just have to do a self join to replicate lead or lag function. Here is example of lead
select t1.field1
,t1.field2
,t2.field1 as lead_field1
,t2.field2 as lead_field2
from table1 t1
left join
(select seq-1 as prev_seq,field1,field2
from table1) t2
on t1.seq=t2.prev_seq
The output of this query will be like this, which is what you need to replicate lead function.
+--------+--------+-------------+-------------+
| field1 | field2 | lead_field1 | lead_field2 |
+--------+--------+-------------+-------------+
| 101 | 1 | 102 | 3 |
| 102 | 3 | 103 | 4 |
| 103 | 4 | 104 | 4 |
| 104 | 4 | 105 | 3 |
| 105 | 3 | NULL | NULL |
+--------+--------+-------------+-------------+
Sample for the same could be found at
http://rextester.com/IJIU40428
Related
NOTE: I WANT TO AVOID DISTINCT ON FOR PERFORMANCE REASONS.
NOTE 2: I WAS WRONG. USING PROPER INDEXES THE QUERY WORKED AWESOME THANKS TO #Gordon Linoff!
Having the following structure:
| id | image_url | sort | t1_id |
|----|---------------|------|-------|
| 1 | https://.../1 | 10 | 1 |
| 2 | https://.../2 | 20 | 1 |
| 3 | https://.../3 | 30 | 1 |
| 4 | https://.../4 | 30 | 2 |
| 5 | https://.../5 | 20 | 2 |
| 6 | https://.../6 | 10 | 2 |
I want to fetch the lowest sort row's image_url column by t1_id, similar to the following:
SELECT * FROM t2 WHERE MIN(sort) GROUP BY (t1_id);
Getting the following result:
| id | image_url | sort | t1_id |
|----|---------------|------|-------|
| 1 | https://.../1 | 10 | 1 |
| 6 | https://.../6 | 10 | 2 |
Thanks in advance!
Postgres has a handy extension called distinct on:
select distinct on (t1_id) t2.*
from t2
order by t1_id, sort asc;
This is usually the fastest way to approach such a problem. In particular, this can take advantage of an index on (t1_id, sort [desc]).
However, you can try another approach such as:
select t2.*
from t2
where t2.sort = (select min(tt2.sort)
from t2 tt2
where tt2.t1_id = t2.t1_id
);
This would use the same index. If this is faster, please post a comment with the relevant performance.
Suppose I have the following table:
+----+-------------+-------------+
| id | step_number | employee_id |
+----+-------------+-------------+
| 1 | 1 | 3 |
| 1 | 2 | 3 |
| 1 | 3 | 4 |
| 2 | 2 | 3 |
| 2 | 3 | 4 |
| 2 | 4 | 5 |
+----+-------------+-------------+
My desired results are:
+----+-------------+-------------+
| id | step_number | employee_id |
+----+-------------+-------------+
| 1 | 1 | 3 |
| 2 | 2 | 3 |
+----+-------------+-------------+
My current solution is:
SELECT
*
FROM
(SELECT
id,
step_number,
MIN(step_number) OVER (PARTITION BY id) AS min_step_number,
employee_id
FROM
table_name) AS t
WHERE
t.step_number = t.min_step_number
Is there a more efficient way I could be doing this?
I'm currently using postgresql, version 12.
In Postgres, I would recommend using distinct on to adress this greatest-n-per-group problem:
select distinct on (id) t.*
from mytbale t
order by id, step_number
This Postgres extension to the SQL standard has usually better performance than the standard approach using window functions (and, as a bonus, the syntax is neater).
Note that this assumes unicity of (id, step_number) tuples: otherwise, the results might be different than those of your query (which allows ties, while distinct on does not).
I have a table with multiple records for each patient.
My end goal is a table that is 1-to-1 between Patient_id and Value.
I would like to de-duplicate (in respect to patient_id) my rows based on "a hierarchical series of aggregate functions" (if someone has a better way to phrase this, I'd appreciate that as well.)
+----+------------+------------+------------+----------+-----------------+-------+
| ID | patient_id | Date | Date2 | Priority | Source | Value |
+----+------------+------------+------------+----------+-----------------+-------+
| 1 | 1 | 2017-09-09 | 2018-09-09 | 1 | 'verified' | 55 |
| 2 | 1 | 2017-09-09 | 2018-11-11 | 2 | 'verified' | 78 |
| 3 | 1 | 2017-11-11 | 2018-09-09 | 3 | 'verified' | 23 |
| 4 | 1 | 2017-11-11 | 2018-11-11 | 1 | 'self_reported' | 11 |
| 5 | 1 | 2017-09-09 | 2018-09-09 | 2 | 'self_reported' | 90 |
| 5 | 1 | 2017-09-09 | 2018-09-09 | 3 | 'self_reported' | 34 |
| 6 | 2 | 2017-11-11 | 2018-09-09 | 2 | 'self_reported' | 21 |
+----+------------+------------+------------+----------+-----------------+-------+
For each patient_id, I would like to get the row(s) that has/have the MAX(Date). In the case that there are still duplicated patient_id, I would like to get the row(s) with the MIN(Priority). In the case that there are still duplicated rows I would like to get the row(s) with the MIN(Date2).
The way I've approached this problem is using a series of queries like this to de-duplicate on the columns one at a time.
SELECT *
FROM #table t1
LEFT JOIN
(SELECT
patient_id,
MIN(priority) AS min_priority
FROM #table
GROUP BY patient_id) t2 ON t2.patient_id = t1.patient_id
WHERE t2.min_priority = t1.priority
Is there a way to do this that allows me to de-dup on multiple columns at once? Is there a more elegant way to do this?
I'm able to get my results, but my solution feels very inefficient, and I keep running into this. Thank you for any input.
You could use row_number(), if your RDBMS supports it:
select ID, patient_id, Date, Date2, Priority, Source, Value
from (
select
t.*,
row_number() over(partition by patient_id order by Date desc, Priority, Date2) rn
from mytable t
) where rn = 1
Another option is to filter with a correlated subquery that sorts the record according to your criteria, like so:
select t.*
from mytable t
where id = (
select id
from mytable t1
where t1.patient_id = t.patient_id
order by t1.Date desc, t1.Priority, t1.Date2
limit 1
)
The actual syntax for limit varies accross RDBMS.
I have the following table:
|-----|-----|
| i d | val |
|-----|-----|
| 1 | 1 |
|-----|-----|
| 2 | 4 |
|-----|-----|
| 3 | 3 |
|-----|-----|
| 4 | 7 |
|-----|-----|
Can I get the following output:
|-----|
| sum |
|-----|
| 1 |
|-----|
| 5 |
|-----|
| 8 |
|-----|
| 1 5 |
|-----|
using a single SQLite3 SELECT-query? I know it could be easily achieved using variables, but SQLite3 lacks those. Maybe some recursive query? Thanks.
No.
In a relational database table rows do not have any order. If you specify an order for the rows, then it's possible to write a query.
Now, you could add an extra column to sort the rows. For example:
| val | sort
|-----|-----
| 1 | 10
| 4 | 20
| 3 | 30
| 7 | 40
The query could be:
select
sum(val) over(order by sort)
from my_table
For the updated question, you can write:
select
sum(val) over(order by id)
from my_table
By using the order of the id column and if you want only the sum column, you can do this:
select (select sum(val) from tablename where id <= t.id) sum
from tablename t
Let's say I have data like this :
| id | code | name | number |
-----------------------------------------------
| 1 | 20 | A | 10 |
| 2 | 20 | B | 20 |
| 3 | 10 | C | 30 |
| 4 | 10 | D | 80 |
I would like to group rows by code value, but get real rows back (not some aggregate function).
I know that just
select *
from table
group by code
won't work because database don't know which row to return where code is the same.
So my question is how to tell database to select (for example) the lower number column so in my case
| id | code | name | number |
-----------------------------------------------
| 1 | 20 | A | 10 |
| 3 | 10 | C | 30 |
P.S.
I know how to do this by PARTITION but this is only allowed in Oracle databases and can't be created in JPA criteria builder (what is my ultimate goal).
Why You don't use code like this?
SELECT
id,
code,
name,
number
FROM
(
SELECT
*,
ROW_NUMBER() OVER (PARTITION BY code ORDER BY number ASC) AS RowNo
FROM table
) s
WHERE s.RowNo = 1
You can look at this site;
Data Partitioning