How to join sequential values - parent-child

I do have a file that contains 2 kinds of records, parents and children:
id type filler
-- ---- ------
1 1500 h1
2 1501 d11
3 1501 d12
4 1501 d13
5 1500 h2
6 1501 d21
7 1501 d22
...
I would like to join records 1501 to respective 1500 record, so, result must be something similar to:
id1 type filler id2 type filler2
--- ---- ------ --- ---- -------
1 1500 h1 2 1501 d11
1 1500 h1 3 1501 d12
1 1500 h1 4 1501 d13
5 1500 h2 6 1501 d21
5 1500 h2 7 1501 d22
...
Is there any way to join parent-child records like these?

To get the order from id and type, the easiest is probably to use common table expressions to tag the rows with their group and join rows of the same group to get the result, something close to;
WITH cte AS (
SELECT *, CASE WHEN type < LAG(type) OVER (ORDER BY id) THEN 1 END cnt
FROM mytable
), cte2 AS (
SELECT id, type, filler, COUNT(cnt) OVER (ORDER BY id) tag FROM cte
)
SELECT a.id, a.type, a.filler, b.id, b.type, b.filler
FROM cte2 a
JOIN cte2 b
ON a.tag = b.tag
WHERE a.type = 1500 AND b.type = 1501
ORDER BY a.id, b.id
id | type | filler | id | type | filler
----+------+--------+----+------+--------
1 | 1500 | h1 | 2 | 1501 | d11
1 | 1500 | h1 | 3 | 1501 | d12
1 | 1500 | h1 | 4 | 1501 | d13
5 | 1500 | h2 | 6 | 1501 | d21
5 | 1500 | h2 | 7 | 1501 | d22

Related

Inner join two tables and list out specific rows

Let's say I have two tables as following:
+--------------+-------+
| ID | Score |
+--------------+-------
| 123 | 88 |
| 456 | 77 |
| 789 | 88 |
| 111 | 77 |
| 555 | 77 |
|444 | 88 |
| 222 | 77 |
| 333 | 88 |
SECOND TABLE:
+--------------+-----+
| ID |NAME | FScore |
+--------------+-------
| 123 |John | 106 |
| 456 |Aaron | 99 |
| 789 |Dan | 105 |
| 111 |Kevin | 200 |
| 555 |Tom | 100 |
| 444 |Jeff | 120 |
| 222 |Carl | 65 |
| 333 |Wayne | 101 |
I want to join two tables and based on FScore find out top 3 88 and top 3 77 rows like:
+--------------+--------------+------+-----+
| ID | Score | NAME | FScore |
+--------------+--------------+------+-----+
| 444 | 88 | Jeff | 120 |
| 123 | 88 | John | 106 |
| 789 | 88 | Dan | 105 |
Any helps are appreciated!
You can use a CTE that returns the joined tables and then filter the resultset with a correlated subquery:
WITH cte AS (
SELECT *
FROM table1 t1 INNER JOIN table2 t2
ON t2.ID = t1.ID
WHERE t1.Score IN ('77', '88')
)
SELECT c1.ID, c1.Score, c1.Name, c1.FScore
FROM cte c1
WHERE (SELECT COUNT(*) FROM cte c2 WHERE c2.Score = c1.Score AND c2.FScore >= c1.FScore) <= 3;
Or, with ROW_NUMBER() window function:
WITH cte AS (
SELECT *, ROW_NUMBER() OVER (PARTITION BY t1.Score ORDER BY t2.FScore DESC) rn
FROM table1 t1 INNER JOIN table2 t2
ON t2.ID = t1.ID
WHERE t1.Score IN ('77', '88')
)
SELECT ID, Score, Name, FScore
FROM cte
WHERE rn <= 3;
See the demo.

How to join three tables following the date?

I have three data tables and they are given below. My first table name is product_table, the second table name is product_purchase_table, and the third table name is product_transfer_table. I'm trying to join these three tables like table name Table After Joint which is given below. My data will be joint once after another following the date like the given Table(Table After Joint).
product_table
row_id product_id product_name
1 101 Accounting Book
Product_Purchase_table
row_id product_id date quantity price
1 101 2020-10-25 100 1000
2 101 2020-10-29 200 2000
Product_transfer_table
row_id product_id date t_quantity t_price
1 101 2020-10-26 10 120
2 101 2020-10-27 15 180
3 101 2020-10-30 5 60
Table After Joint
row_id product_id product_name date quantity price t_quantity t_price
1 101 Accounting Book 2020-10-25 100 1000
2 101 Accounting Book 2020-10-26 10 120
3 101 Accounting Book 2020-10-27 15 180
4 101 Accounting Book 2020-10-29 200 2000
5 101 Accounting Book 2020-10-30 5 60
You need a FULL OUTER join of Product_Purchase_table and Product_transfer_table (emulated by LEFT joins and UNION ALL because SQLite does not support FULL OUTER join) and INNER join the result to product_table
SELECT row_number() over (partition by pt.product_id order by t.date) row_id,
pt.product_id, pt.product_name,
t.date, t.quantity, t.price, t.t_quantity, t.t_price
FROM product_table pt
INNER JOIN (
SELECT ppt.product_id, ppt.date, ppt.quantity, ppt.price,
ptt.t_quantity, ptt.t_price
FROM Product_Purchase_table ppt LEFT JOIN Product_transfer_table ptt
ON ptt.product_id = ppt.product_id AND ptt.date = ppt.date
UNION ALL
SELECT ptt.product_id, ptt.date, ppt.quantity, ppt.price,
ptt.t_quantity, ptt.t_price
FROM Product_transfer_table ptt LEFT JOIN Product_Purchase_table ppt
ON ptt.product_id = ppt.product_id AND ptt.date = ppt.date
WHERE ppt.product_id IS NULL
) t ON t.product_id = pt.product_id
ORDER BY pt.product_id, t.date
See the demo.
Results:
> row_id | product_id | product_name | date | quantity | price | t_quantity | t_price
> -----: | ---------: | :-------------- | :--------- | -------: | ----: | :--------- | :------
> 1 | 101 | Accounting Book | 2020-10-25 | 100 | 1000 | null | null
> 2 | 101 | Accounting Book | 2020-10-26 | null | null | 10 | 120
> 3 | 101 | Accounting Book | 2020-10-27 | null | null | 15 | 180
> 4 | 101 | Accounting Book | 2020-10-29 | 200 | 2000 | null | null
> 5 | 101 | Accounting Book | 2020-10-30 | null | null | 5 | 60

Populating the blank values of a column based on same values in another column using R

I have a sample dataset:
df= data.frame(Id=c(NA, "601","865",NA,"743"), Date= as.Date(c("12/23/2019","12/12/2019","12/23/2019",
"11/21/2019","12/19/2019"), format = "%m/%d/%Y" ),
Amount=c(1100,-1100,-5055,675,-675), stringsAsFactors = F)
which would look like:
| Id | Date | Amount |
|-----|:----------:|-------:|
| NA | 12/23/2019 | 1100 |
| 601 | 12/12/2019 | -1100 |
| 865 | 12/23/2019 | -5055 |
| NA | 11/21/2019 | 675 |
| 743 | 12/19/2019 | -675 |
Now, what I want to do is to populate the NA rows of column 'Id' such that the NA in Id will be populated with the same Id values having same amount. In other words, when the amount is same (irrespective of it being a positive or a negative value), the NA Id value will be populated with the same value Id value having the same amount. In the above example, we see that the first row has NA and the second row has Id value of 601. Since both belong to same amount 1100 (ignore the positive and negative values), the NA should be populated with same Id value, i.e., 601. The third row does not have multiple occurrence with NA in the Id column, so we will move ahead with the next row which has a NA with same amount value as the fifth row and populate it. The final output should look like the one below:
| Id | Date | Amount |
|-----|:----------:|-------:|
| 601 | 12/23/2019 | 1100 |
| 601 | 12/12/2019 | -1100 |
| 865 | 12/23/2019 | -5055 |
| 743 | 11/21/2019 | 675 |
| 743 | 12/19/2019 | -675 |
You can try this:
df$Id[is.na(df$Id)] <- df$Id[!is.na(df$Id)][match(abs(df$Amount[is.na(df$Id)]), abs(df$Amount[!is.na(df$Id)]))]
df
#> Id Date Amount
#> 1 601 2019-12-23 1100
#> 2 601 2019-12-12 -1100
#> 3 865 2019-12-23 -5055
#> 4 743 2019-11-21 675
#> 5 743 2019-12-19 -675

get row values to one column recursively (and doing combinations)

I have one input table, it has dates and a fixed number of events. I need to create, from it, the list of events with date of occurrence, and the list of combined events and their occurrence.
Example:
initial table:
CREATE TABLE events (
date DATE PRIMARY KEY,
e1 INTEGER,
e2 INTEGER,
e3 INTEGER
);
date | e1 | e2 | e3 |
--------------------------
2017-02-04 | 2 | 1 | 26 |
2017-02-05 | 14 | 2 | 1 |
2017-02-06 | 1 | 3 | 2 |
Output 1
eventN | total | date1 | date2 |...| date'N'
--------------------------------------------------------
01 | 3 | 2017-02-04 | 2017-02-05 |...| 2017-02-06
02 | 2 | 2017-02-05 | 2017-02-06 |...| (null)
...
26 | 1 | 2017-02-04 | (null) |...| (null)
Output 2
CobineEventN | total | date1 | ... | date'N'
-----------------------------------------------------
0102 | 2 | 2017-02-05 | ... | 2017-02-06
0103 | 1 | 2017-02-06 | ... | (null)
....
2526 | 1 | 2017-02-04 | ... | (null)
....
Limitations:
this has to be done in SQLite.
there is no limit for the dates (i.e. 'n' unique dates).
the events, are a fixed list of (around)50 ids
the output will be tables, one for each type of combination.
the author SQL skills.
After some talk with a teacher, he pointed out that my model was all wrong from start.
changing the table to:
REATE TABLE event (id integer NOT NULL PRIMARY KEY AUTOINCREMENT, date date NOT NULL, event smallint unsigned NOT NULL);
*'id' is unnecessary
something like:
Id date event
31 2016-10-05 1
44 2016-10-07 1
32 2016-10-05 2
I could use a query like:
select A.event as nA, B.event as nB, C.event as nC, date
from event as A, event as B, event as C
where A.date = B.date
and B.date=C.date
and nC<>nA
and nC<>nB
and obtain the values needed.
nA nB nC date
1 2 3 2016-10-05
1 2 3 2016-10-07
1 2 4 2016-10-07
...
Although the format is not exactly what I had imagined, the results work fine.
And I don't need to create any more columns for the rest of the project, just have to do the right queries.
BR

SQL - selecting multiple tables so as to combine multiple tables

I want to use SELECT * from multiple tables table1 and table2 to get the output table which is nothing but table2 data appended to table1. How do I construct the SELECT * FROM statement ?
Table1:
id model datetime driver distance
---|-----|------------|--------|---------
1 | S | 04/03/2009 | john | 399
2 | X | 04/03/2009 | juliet | 244
3 | 3 | 04/03/2009 | borat | 555
Table2:
id model datetime driver distance
---|-----|------------|--------|---------
4 | 3 | 03/03/2009 | john | 300
5 | X | 03/03/2009 | juliet | 200
Desired output:
model datetime driver distance
-----|------------|--------|---------
S | 04/03/2009 | john | 399
X | 04/03/2009 | juliet | 244
3 | 04/03/2009 | borat | 555
3 | 03/03/2009 | john | 300
X | 03/03/2009 | juliet | 200
Try this out this might help you
SELECT table1.model, table1.datetime, table1.driver, table1.distance FROM table1
UNION ALL SELECT table2.model, table2.datetime, table2.driver, table2.distance FROM table2;
union statement get slow for fetching the large data from the db, you can use join here,
select * from table0 left join table2 on table0.b = table2.b where table2.col is not null

Resources