Hive Find Start and End of Group or Changing point - sql

Here is the table:
+------+------+
| Name | Time |
+------+------+
| A | 1 |
| A | 2 |
| A | 3 |
| A | 4 |
| B | 5 |
| B | 6 |
| A | 7 |
| B | 8 |
| B | 9 |
| B | 10 |
+------+------+
I want to write a query to get:
+-------+--------+-----+
| Name | Start | End |
+-------+--------+-----+
| A | 1 | 4 |
| B | 5 | 6 |
| A | 7 | 7 |
| B | 8 | 10 |
+-------+--------+-----+
Does anyone know how to do it?

This is not the most efficient way, but it this works.
SELECT name, min(time) AS start,max(time) As end
FROM (
SELECT name,time, time- DENSE_RANK() OVER (partition by name ORDER BY
time) AS diff
FROM foo
) t
GROUP BY name,diff;
I would suggest try the following query and build a GenericUDF to identify the gaps, much more easier :)
SELECT name, sort_array(collect_list(time)) FROM foo GROUP BY name;

Related

Postgresql: Group rows in a row and add array

Hi i have a table like this;
+----+----------+-------------+
| id | room_id | house_id |
+----+----------+-------------+
| 1 | 1 | 1 |
| 2 | 2 | 1 |
| 3 | 3 | 1 |
| 4 | 1 | 2 |
| 5 | 2 | 2 |
| 6 | 3 | 2 |
| 7 | 1 | 3 |
| 8 | 2 | 3 |
| 9 | 3 | 3 |
+----+-------+----------------+
and i want to create a view like this
+----+----------+-------------+
| id | house_id | rooms |
+----+----------+-------------+
| 1 | 1 | [1,2,3] |
| 2 | 2 | [1,2,3] |
| 3 | 3 | [1,2,3] |
+----+-------+----------------+
i tried many ways but i cant gruop them in one line
Thanks for any help.
You can use array_agg():
select house_id, array_agg(room_id order by room_id) as rooms
from t
group by house_id;
If you want the first column to be incremental, you can use row_number():
select row_number() over (order by house_id) as id, . . .

Add Index to postgreSQL query result

My query result looks like this:
| A | B |
|-------|
| 1 | 2 |
| 1 | 4 |
| 1 | 6 |
| 1 | 9 |
| 1 | 1 |
| 1 | 6 |
| 1 | 9 |
Now I want to increase column A by the index of the result table, so the result would become like this:
| A | B |
|-------|
| 2 | 2 |
| 3 | 4 |
| 4 | 6 |
| 5 | 9 |
| 6 | 1 |
| 7 | 6 |
| 8 | 9 |
How can I do it?
Thanks!
You want row_number()
select (row_number() over (order by a) + 1) as A, b
from table t;
Maybe something like that:
SELECT
(row_number() OVER (ORDER BY A) + A) AS columnAIndex,
columnB
FROM ...
I don't have a PostgreSQL client installed here, therefore, i don't tested this query.

Limit a sorted number of rows joined

I have two tables, A and B, and a join table M. I want to, for each A.id, get the top 2 B.id's sorting on the value in table M, producing the results below. This is running on an Azure SQL database
Table A Table M Table B
+-----+ +-----+-----+-------+ +-----+
| Id | | AId | BId | Value | | Id |
+-----+ +-----+-----+-------+ +-----+
| 1 | | 1 | 3 | 4 | | 1 |
| 2 | | 1 | 2 | 3 | | 2 |
| 3 | | 3 | 2 | 3 | | 3 |
| 4 | | 3 | 5 | 6 | | 4 |
+-----+ | 3 | 3 | 4 | | 5 |
| 4 | 1 | 2 | +-----+
| 4 | 2 | 1 |
| 4 | 4 | 3 |
+-----+-----+-------+
Result
+-----+-----+-------+
| AId | BId | Value |
+-----+-----+-------+
| 1 | 3 | 4 |
| 1 | 2 | 3 |
| 3 | 5 | 6 |
| 3 | 3 | 4 |
| 4 | 1 | 2 |
| 4 | 4 | 3 |
+-----+-----+-------+
I know that I can select all the M.AId rows where they equal 1, sort it, and limit by 2, but I need to do this for every row in Table A. I've made an attempt to use group by, but I wasn't sure how to sort and limit it. I've also tried to search for resources associated with this issue but I couldn't find any resources.
(I also wasn't sure how to word the title for this issue)
You can just use ROW_NUMBER:
SELECT
AId, BId, Value
FROM (
SELECT *,
Rn = ROW_NUMBER() OVER(PARTITION BY AId ORDER BY Value DESC)
FROM M
) t
WHERE Rn <= 2

Showing data from another table if it exists

I am having a hard time trying to get the correct data out of my DB.
I have a couple of tables:
events_template laser_events
| id | something | | id | extid | added |
================== ===========================
| 1 | something | | 1 | 7 | added |
| 2 | something | | 2 | 4 | added |
| 3 | something | | 3 | 2 | added |
| 4 | something | | 4 | 1 | added |
| 5 | something | | 5 | 9 | added |
| 6 | something | | 6 | 3 | added |
| 7 | something |
| 8 | something |
| 9 | something |
| 10 | something |
| 11 | something |
| 12 | something |
| 13 | something |
| 14 | something |
What I am trying to do is get some output that will show me the results of both tables together linked by id and extid, but still show the results from events_template even if there isn't a matching laser_events row.
I've tried something like
SELECT
id,
extid
FROM
events_template,
laser_events
WHERE
events_template.id = laser_events.ext_id;
But that doesn't show me the events_template rows if there isn't a matching laser_events row.
Any help would be appreciated!
You have to use LEFT JOIN:
SELECT e.id, l.ext_id
FROM events_template e
LEFT JOIN laser_events l ON e.id = l.ext_id;

SQL - only display rows that have the max value

I have this table that is already sorted but I want it to only display the maximum values... so instead of this table:
+------+-------+
| id | value |
+------+-------+
| 1 | 3 |
| 5 | 3 |
| 4 | 3 |
| 9 | 2 |
| 8 | 2 |
| 3 | 2 |
| 2 | 1 |
| 6 | 1 |
| 7 | 1 |
+------+-------+
I want this:
+------+-------+
| id | value |
+------+-------+
| 1 | 3 |
| 5 | 3 |
| 4 | 3 |
+------+-------+
I'm using SQLite. thanks for any help.
You can do this using a subquery. Here is one way:
select t.*
from t
where t.value = (select max(value) from t);