Retrieving rows based on a list of IDs in MySQL - mysql

I'm trying to retrieve all the rows in a table with children variables where the Foreign Key of those rows is equal to the Primary Key of rows in a table with parent variables.
Graphically it looks something like this:
Table 1. This table contains the parent rows.
ID | variable | variable | etc.
1 | XX | BB | ...
2 | YY | AA | ...
Table 2. This table contains the children rows.
ID | FK (parent) | variable | etc.
1 | 1 | BB | ...
2 | 1 | AA | ...
3 | 1 | AA | ...
4 | 2 | AA | ...
5 | 3 | AA | ...
I'm obviously not an expert in SQL, what I would normally do in another programming language is writing a loop that cycles through every row in the parent table, and then checks the children table if there is a match. I have, however, no idea of what would be the most efficient approach here. The parent table will have 50+ rows. The children table has 8000+ rows.
UPDATE: I want to dump the relevant data from the children table in a new table. So I do not want a combined table with data from the parent and children table, which is what a JOIN does I think.
UPDATE 2: I managed to get what I wanted through:
INSERT INTO NewTable
select columns
from ChildrenTable t
inner join ParentTable p
on t.parentId = p.Id
Thanks for the help!

You can try like this-
Select * from table1 left join table2 on table1.id = table2.fk

You wrote:
I want to dump the relevant data from the children table in a new
table. So I do not want a combined table with data from the parent and
children table, which is what a JOIN does I think.
Well JOIN just combines two or more relevant data from chosen tables. What I mean is you can SELECT whatever columns you want i.e. if you have such tables (a bit updated columns from your original table):
parent-table
ID | variable1 | variable2 | etc.
1 | XX | BB | ...
2 | YY | AA | ...
child-table
ID | FK-ID | variable | etc.
1 | 1 | BB | ...
2 | 1 | AA | ...
3 | 1 | AA | ...
4 | 2 | AA | ...
5 | 3 | AA | ...
And you want to retrieve only ID from first table, variabl2 from first table and variable from second one you would write
SELECT ID.parent-table, variable2.parent-table, variable.child-table
FROM parent-table
JOIN child-table ON parent-table.ID = FK-ID.child-table;
Or if you don't like joins you can ignore them and just get data from both tables and specify where clause i.e.
SELECT ID.parent-table, variable2.parent-table, variable.child-table
FROM parent-table, child-table
WHERE parent-table.ID = FK-ID.child-table;
Both above written queries are equivalent. If you want you can create a new table, let's call it parent-child-table with that data which will be a separate copy. Or if you need to use it a lot you can create a VIEW (you can google about it) which is virtual table (it stores a query), for example let's call it parent-child-view if you make some changes in parent-table and child-table changes will be reflected in parent-child-view but if you create a separate new table parent-child-table changes won't be reflected because it's just a copy.

You can Try using:
select * from table2, table1 where table2.fk = table1.id

select * from child_table_name as tblchild, parent_table_name as tblparent, where tblchild.fk_column_name=tblparent.id

Related

Count rows referring to a particular row, multiple referencing tables in MySql?

My question is the following:
As asked in the question "How to count amount of rows referring to a particular row foreign key in MySql?", I want to count table references involving multiple tables referring to the table I'm interested about. However here we want the specific number of references per row for the resourced table.
In addition, what about the variant where the tables do reference eachother, but the foreign key does not exist?
Let's setup some minimal examples;
We have three tables, here called A, B, and C. B and C refer rows in A. I want to count the total amount of references for each row in A.
Contents of the first table (A), and expected query results in the column 'Count':;
+----+------------+-------+
| ID | Name | Count |
+----+------------+-------+
| 1 | First row | 0 |
| 2 | Second row | 5 |
| 3 | Third row | 2 |
| 4 | Fourth row | 1 |
+----+------------+-------+
Contents of the second table (B):
+----+------+
| ID | A_ID |
+----+------+
| 1 | 2 |
| 2 | 2 |
| 3 | 2 |
+----+------+
Contents of the third table (C):
+----+------+
| ID | A_ID |
+----+------+
| 1 | 2 |
| 2 | 2 |
| 3 | 3 |
| 4 | 3 |
| 5 | 4 |
+----+------+
Important restrictions for a solution
The solution should work with n tables, for reasonable values of n. The example has n=2.
The solution should not involve a subset of the product set of all the tables. As some rows from A may be referenced a bunch of times in all the other tables the size of the product set may well be stupidly large (e.g. 10*10*10*... becomes big quickly). E.g. it may not be O(q^n) where n is the number of tables and q is the amount of occurrences.
This is a partial solution, which I believe still suffers from performance problems related to condition [2]
I'm adding this as an answer as it may be useful for those working towards a better solution
Apply the following query. Extend as necessary with additional tables, adding additional lines to both the sum and the set of JOINs. This particular solution will work as long as you have less than about 90 tables. With more than that, you will have to run multiple queries like it and cache the results (for example by creating a column in the 'A' table), then sum all these later on.
SELECT
COUNT(DISTINCT B.ID) +
COUNT(DISTINCT C.ID) -- + .....
AS `Count`
FROM A
LEFT JOIN B ON A.ID = B.A_ID
LEFT JOIN C ON A.ID = C.A_ID
Unfortunately, if you have often referenced rows, the query will have a massive intermediate result, run out of memory, and thus never complete.

Copy a table and replace foreign surrogate key column with text column

I am building a database / application in MySQL. I am trying to create a Stored Procedure that returns a table of all children that are currently linked to a parent, for display.
The children table is going to be populated with up to 100,000 records.
I want the returned table to be a copy of the child table, except the foreign key column linking the children to the parent (current and previous) should be replaced by a text column containing the parents name, (I don't want to return a surrogate key for display)
These are my two tables
Parent
PARENTID | PARENTNAME
-------------------------
1 | NAME1
2 | NAMETWO
3 | ANOTHERNAME
Child
CHILDNAME | CURRENTPARENTID | PREVIOUSPARENTID | OTHERDATA COLUMNS...
-----------------------------------------------------------------------
123ABC | 2 | 3 | ..
124ABC | 2 | 1 | ..
125ABC | 1 | 2 | ..
And when I call the stored procedure to return all children with currentparentID = 2, for instance, I would like the table returned to be
CHILDNAME | CURRENTPAR_NAME| PREVIOUSPAR_NAME | OTHERDATA COLUMNS...
-----------------------------------------------------------------------
123ABC | NAMETWO | ANOTHERNAME | ..
224ABC | NAMETWO | NAME1 | ..
I can't figure how the INSERT INTO statement would be made
Would it be easier / more efficent to just return the raw children table filtered to currentparentid = 2, and do the assignment on the application side?
Cheers
How about an insert statement like this:
INSERT INTO NewTable(CHILDNAME, CURRENTPAR_NAME, PREVIOUSPAR_NAME)
SELECT c.CHILDNAME, p1.PARENTNAME, p2.PARENTNAME
FROM Child c
JOIN Parent p1 ON (p1.PARENTID = c.CURRENTPARENTID)
JOIN Parent p2 ON (p2.PARENTID = c.PREVIOUSPARENTID)
;
Depending on the structure of the child table, whether it is active, etc, you could tack on a WHERE clause to do the insert in chunks.

Mysql: how to return value or empty string from column ids in table (multi table)

I'M trying to extract all information into my table, but I need to change id, when available, to the name into another table.
I have 1 table like that:
|------------------------------|
|-id-|-systems-|-remote-|-deco-|
| 1 | NULL | 3 | |
| 2 | 21 | NULL | 2 |
|-------------------------------
each column like "systems" / "remote" / "deco" refer to an id into another table
I know how to use INNER JOIN. But if I use that, I got an empty result because the value need to be appears into the others tables.
ex.:
SELECT qd.id,s.name as systems,r.name as remote, d.name as deco
FROM `quote_data` qd
INNER JOIN systems s ON qd.systems=s.id
INNER JOIN remote r ON qd.remote=r.id
INNER JOIN deco d ON qd.deco=d.id
I got empty result.
In the best words, I need to do something like:
|------------------------------|
|-id-|-systems-|-remote-|-deco-|
| 1 | | R42 | |
| 2 | GTV | | B21 |
|-------------------------------
Also, I use innoDB table
Any Idea how to fix that?

MYSQL query fetching DATA from two table using IN method one as composition of multiple data

I have two tables
one as td_job which has these structure
|---------|-----------|---------------|----------------|
| job_id | job_title | job_skill | job_desc |
|------------------------------------------------------|
| 1 | Job 1 | 1,2 | |
|------------------------------------------------------|
| 2 | Job 2 | 1,3 | |
|------------------------------------------------------|
The other Table is td_skill which is this one
|---------|-----------|--------------|
|skill_id |skill_title| skill_slug |
|---------------------|--------------|
| 1 | PHP | 1-PHP |
|---------------------|--------------|
| 2 | JQuery | 2-JQuery |
|---------------------|--------------|
now the job_skill in td_job is actualy the list of skill_id from td_skill
that means the job_id 1 has two skills associated with it, skill_id 1 and skill_id 2
Now I am writing a query which is this one
SELECT * FROM td_job,td_skill
WHERE td_skill.skill_id IN (SELECT td_job.job_skill FROM td_job)
AND td_skill.skill_slug LIKE '%$job_param%'
Now when the $job_param is PHP it returns one row, but if $job_param is JQuery it returns empty row.
I want to know where is the error.
The error is that you are storing a list of id's in a column rather than in an association/junction table. You should have another table, JobSkills with one row per job/skill combination.
The second and third problems are that you don't seem to understand how joins work nor how in with a subquery works. In any case, the query that you seem to want is more like:
SELECT *
FROM td_job j join
td_skill s
on find_in_set(s.skill_id, j.job_skill) > 0 and
s.skill_slug LIKE '%$job_param%';
Very bad database design. You should fix that if you can.

SELECT from Union x 3 using filter of another table

Background
I have a web application which must remove entries from other tables, filtered through a selection of 'tielists' from table 1 -> item_table 1, table 2, table 3.... now basically my result set is going to be filthy big unless I use a filter statement from another table, using a user_id... so can someone please help me structure my statement as needed? TY!
Tables
cars_belonging_to_user
-----------------------------
ID | user_id | make | model
----------------------------
1 | 1 | Toyota | Camry
2 | 1 |Infinity| Q55
3 | 1 | DMC | DeLorean
4 | 2 | Acura | RSX
Okay, Now the three 'tielists'
name:tielist_one
----------------------------
id | id_of_car | id_x | id_y|
1 | 1 | 12 | 22 |
2 | 2 | 23 | 32 |
-----------------------------
name:tielist_two
-------------------------------
id | id_of_car | id_x | id_z|
1 | 3 | 32 | 22 |
-----------------------------
name: tielist_three
id | id_of_car | id_x | id_a|
1 | 4 | 45 | 2 |
------------------------------
Result Set and Code
echo name_of_tielist_table
// I can structure if statements to echo result sets based upon the name
// Future Methodology: if car_id is in tielist_one, delete id_x from x_table, delete id_y from y_table...
// My output should be a double select base:
--SELECT * tielists from WHERE car_id is 1... output name of tielist... then
--SELECT * from specific_tielist where car_id is 1.....delete x_table, delete y_table...
Considering the list will be massive, and the tielist equally long, I must filter the results where car_id(id) = $variable && user_id = $id....
Side Notes
Only one car id will appear once in any single tielist..
This select statement MUST be filtered with user_id = $variable... (and remember, i'm looking for which car id too)
I MUST HAVE THE NAME of the tielist it comes from able to be echo'd into a variable...
I will only be looking for one single id_of_car at any given time, because this select will be contained in a foreach loop.
I was thinking a union all items would do the trick to select the row, but how can I get the name of the tielist the row is in, and how can the filter be used from the user_id row
If you want performance, I would suggest left outer join instead of union all. This will allow the query to make efficient use of indexes for your purpose.
Based on what you say, a car is in exactly one of the lists. This is important for this method to work. Here is the SQL:
select cu.*,
coalesce(tl1.id_x, tl2.id_x, tl3.id_x) as id_x,
tl1.y, tl2.idz, tl3.id_a,
(case when tl1.id is not null then 'One'
when tl2.id is not null then 'Two'
when tl3.id is not null then 'Three'
end) as TieList
from Cars_Belonging_To_User cu left ouer join
TieList_One tl1
on cu.id_of_car = tl1.id_of_car left outer join
TieList_Two tl2
on cu.id_of_car = tl2.id_of_car left outer join
TieList_Three tl3
on cu.id_of_car = tl3.id_of_car;
You can then add a where clause to filter as you need.
If you have an index on id_of_car for each tielist table, then the performance should be quite good. If the where clause uses an index on the first table, then the joins and where should all be using indexes, and the query will be quite fast.