SQL Query with "feedback loop" - mysql

Currently, I am using MySQL
I have 2 tables:
Table objects:
| id | desc |
| 1 | 'A' |
| 2 | 'B' |
| 3 | 'C' |
| 4 | 'D' |
| 5 | 'E' |
Table implies:
| id1 | id2 |
| 1 | 2 |
| 1 | 3 |
| 2 | 4 |
| 2 | 5 |
| 3 | 5 |
Table Implies columns id1 and id2 are both foreign keys to table objects id.
Which means:
object 1 implies object 2 and object 3.
object 2 implies object 4 and object 5
object 3 implies object 5
Therefore, Object 1, implies 2, 3, and 4 and 5 (Since 2 implies 4 and 5)
Is there any way to create a query for this behaviour? My current solution consists on calling recursively from java the query until I don't get any new info:
SQL Query Im calling:
SELECT o.id, i.id2
FROM objects o
INNER JOIN implies i ON o.id = i.id1 WHERE id = 1;
I first call it with id = 1, then with id IN (2, 3)... etc
The kind of result I want to achieve:
SELECT ... WHERE id = 1
should return:
| id | id2 |
| 1 | 2 |
| 1 | 3 |
| 1 | 4 |
| 1 | 5 |

Related

Mysql explode json array to rows

From a table with a column with json array of dictionaries i need to extract all values of key "user_id" one per row. If null or empty array return NULL. Similar to python pandas explode method.
Length of array is unknown.
Original table:
| id | users |
|----|-----------------------------------------------------------------|
| 1 |[{"id": 2, "mail": "u1#ab.com"}, {"id": 3, "mail": "u2#ab.com"}] |
| 2 |[{"id": 5, "email": "user3#hi.com"}]" |
| 3 | []
|
Processed table:
| id | users |
|----|----------|
| 1 | 2 |
| 1 | 3 |
| 2 | 5 |
| 3 | NULL |
select id, j.user_id from mytable left outer join
json_table(users, '$[*]' columns (user_id int path '$.user_id')) as j on true;
+------+---------+
| id | user_id |
+------+---------+
| 1 | 2 |
| 1 | 3 |
| 2 | 5 |
| 3 | NULL |
+------+---------+
Read https://dev.mysql.com/doc/refman/8.0/en/json-table-functions.html for more information on the JSON_TABLE() function.

Select all except if specific cell value in MYSQL

I'm stuck and I can't figure it out, so I would appreciate any help.
At this point i have table journal which consists of columns:
id | name | type(int) | classification | data | journalUser | start_date(default NULL)
1 | John | 1 | 2 | data123 | 1 | 10-11-2019
2 | Peter | 2 | 2 | data123 | 1 | 10-11-2019
3 | Ash | 2 | 2 | data123 | NULL | NULL
4 | BUBU | 2 | 2 | data123 | 3 | 10-11-2019
I want to make query where I select all, but with exceptions, for example: SELECT * from journal, but if column type = 2, than select this row too if journalUser = 1 AND second check if column type = 2 and start_date IS NULL, than select this row too.
As the result, from table above, from query I wan to get result
id | name | type(int) | classification | data | journalUser | start_date(default NULL)
1 | John | 1 | 2 | data123 | 1 | 10-11-2019
2 | Peter | 2 | 2 | data123 | 1 | 10-11-2019
3 | Ash | 2 | 2 | data123 | NULL | NULL
That's a specific case when the type is 2.
To get the rows with type = 2 along with either (considering the expected output) journalUser = 1 or start_date = null, this can be written this way :
type = 2 AND (journalUser = 1 OR start_date IS NULL)
To make sure you have others type too, you can add an OR condition such as :
OR type <> 2.
This will give this query :
SELECT *
FROM journal
WHERE (type = 2 AND (journalUser = 1 OR start_date IS NULL))
OR type <> 2

MySQL update table from a EAV table using case when

I have a EAV table. I want to convert this into a normal table in a single query. How can I do this?
Table A
| ID | Entity | Attribute |
+----+--------+-----------+
| 1 | AA | 5 |
| 2 | AA | 2 |
| 3 | AA | 4 |
| 1 | BB | 6 |
| 2 | BB | 5 |
Table B (intended. This has only ID as of now)
| ID | AA | BB |
+----+-----+------+
| 1 | 5 | 6 |
| 2 | 2 | 5 |
| 3 | 4 | NULL |
I tried the following:
update B join A using(ID) set b.AA=(case when Entity='AA' then Attribute end),b.BB=(case when Entity='BB' then Attribute end);
update B join A using(ID) set b.AA=(case when Entity='AA' then Attribute else AA end),b.BB=(case when Entity='BB' then Attribute else BB end);
But the table is not getting updated. Both the fields are set to NULL for all the IDs. I can write separate update queries for each Entity, but I have >100 different entities and each query takes hours to run (I have many records).

Select Distinct Set Common to Subset From Join Table

Given a join table for m-2-m relationship between booth and user
+-----------+------------------+
| booth_id | user_id |
+-----------+------------------+
| 1 | 1 |
| 1 | 2 |
| 1 | 5 |
| 1 | 9 |
| 2 | 1 |
| 2 | 2 |
| 2 | 5 |
| 2 | 10 |
| 3 | 1 |
| 3 | 2 |
| 3 | 3 |
| 3 | 4 |
| 3 | 6 |
| 3 | 11 |
+-----------+------------------+
How can I get a distinct set of booth records that are common between a subset of user ids? For example, if I am given user_id values of 1,2,3, I expect the result set to include only booth with id 3 since it is the only common booth in the join table above between all user_id's provided.
I'm hoping I'm missing a keyword in MySQL to accompish this. The furthest I've come so far is using ... user_id = all (1,2,3) but this is always returning an empty result set (I believe I understand why it is though).
The SQL query for this will be:
select booth_id from table1 where [user_id]
in (1,2,3) group by booth_id having count(booth_id) =
(select count(distinct([user_id])) from table1 where [user_id] in (1,2,3))
If this could help you creating the MySQL query.

mysql getting data and looking it up in another table

I've got two tables in my database. Table 1 is a list of "timelines" and their corresponding owners and title.
Table 2 is a list of users who have access to the timelines but are followers, not owners.
I'm trying to write a query that outputs the lineID's and corresponding titles that are linked to a userID in either of the two tables.
A query for userID 1 would ideally output:
1 a
2 b
3 c
6 f
Hopefully this isn't too confusing but the purpose is to fill a dynamically generated select box with the LineID and Title for a given UserID...
Table 1 ("owners")
--------------------------
| LineID | UserID | Title |
| 1 | 1 | a |
| 2 | 1 | b |
| 3 | 1 | c |
| 4 | 2 | d |
| 5 | 2 | e |
| 6 | 1 | f |
--------------------------
Table 2 ("followers")
----------------------------
| RowID | LineID | UserID |
| 1 | 1 | 1 |
| 2 | 1 | 2 |
| 3 | 3 | 1 |
| 4 | 3 | 2 |
| 5 | 2 | 2 |
| 6 | 6 | 1 |
----------------------------
I tried using:
SELECT title
FROM `lines`
LEFT JOIN follow
ON follow.user_id = lines.user_id
WHERE follow.user_id = 1
That ended up producing duplicate rows.
The output I need would ideally be an array consisting of all the lineID's and Titles associated with that userID.
select LineId, Title
from owners
where LineId in (select LineId from followers group by LineId )
order by owners.LineId