get column value with ID as foreign key in recursion - mysql

I have created a temp table from recursion (CTE), then left join PARAM_VALUE from another table. My temp table look like this
I have the BOQ_ITEM_FK which points to ID having the PARAM_VALUE. I want to get the PARAM_VALUE from the parent ID and apply it to the child PARAM_VALUE.
What I have tried:
SELECT ID, BRIEF, REFERENCE, PARAM_VALUE
FROM #BOQ_TABLE
WHERE ID IN (SELECT BOQ_ITEM_FK FROM #BOQ_TABLE)
But I only get:
Thanks in advance

In order to get the PARAM_VALUE from another related row in the same table, you'll need to join the table with itself.
When a query includes the same table multiple times you need to assign an alias to each table instance, in order to identify where each column is coming from. I chose the aliases a and b but you are free to choose any alias that makes sense to you.
Your query could look like:
select
a.id,
a.brief,
a.reference,
b.param_value
from #boq_table a
left join #boq_table b on b.id = a.boq_item_fk
Notice that:
The PARAM_VALUE column is coming from the second table instance and, therefore, comes from a different row.
The query uses an outer join (LEFT JOIN) in case the parent row does not exist.

Related

Create table from joined table in MySQL

I have no problem joining the tables, but when I go to create a new table using the joined tables, I get an error saying that I have duplicate columns.
My code:
SELECT *
FROM field
INNER JOIN race
ON field.raceID = race.raceID;
Updated code:
CREATE TABLE fieldrace AS
SELECT f.*, r.*
FROM field f
INNER JOIN race r
ON f.raceID = r.raceID;
That's true of any select. If there are duplicated column names, you have to reference them somehow. For a .* query this would work:
SELECT f.*, r.*
FROM field f
INNER JOIN race r
ON f.raceID = r.raceID;
Individually you can also add aliases. Maybe you have an id column in both race and field tables.
SELECT f.id as field_id, r.id as race_id, ....
FROM field f
INNER JOIN race r
ON f.raceID = r.raceID;
In the query
CREATE TABLE fieldrace AS
SELECT f.*, r.*
FROM field f
INNER JOIN race r
ON f.raceID = r.raceID;
SELECT part produces two columns with the same name in the output.
Two columns with the same name presence is not allowed in table's structure, and the whole query will fail.
General solution is to list each output column in the SELECT part separately with assigning them unique aliases.
If raceID column which is used for joining is the only column whose name interferes then you may use either USING clause instead of ON clause or NATURAL JOIN instead of INNER JOIN.
CREATE TABLE fieldrace AS
SELECT f.*, r.*
FROM field f
INNER JOIN race r USING (raceID);
-- or
CREATE TABLE fieldrace AS
SELECT f.*, r.*
FROM field f
NATURAL INNER JOIN race r;
In both cases the interfered columns will be collapsed into one column which will be placed to the top of created table structure.
Of course when raceID is not the only column whose name interferes then 1st of these queries will fail due to another column duplication whereas 2nd query will use all interfered columns for joining.
You may specify complete or partial structure of newly create table. In this case the amount and relative posession of the columns in the created table won't be changed (will match SELECT output) but all another properties of the columns (datatype, nullability, etc.) and additional objects (indices, constraints, etc.) listed in the structure will be applied. The columns which are absent in the output (including generated ones) will be added into the structure with default values as the most first ones, before the columns used in USING or during NATURAL JOIN even. DEMO.
you can create "view" or name a subquery using "with"
in both cases, you can access it from anywhere in your main query

SQL Select non intersecting elements from the super set

How to choose the records in A that doesn't intersect with B? The records in A and B are already derived from a couple of inner joins. I tried left join, and right and not exists too, it's giving inappropriate results.
SELECT id FROM A_List
MINUS
SELECT id FROM B_List;
In here give your column name instead of id and remember same column name to give both A and B lists. Give your derived (with inner join) A list and B list for A_List and B_List and try this.

SQL: Remove records from table A that don't exist in table B based on two fields

this is probably something simple but I can't wrap my head around it. I've tried IN, NOT EXISTS, EXCEPT, etc... and still can't seem to get this right.
I have two tables.
Table A
-----------
BK
NUM
Table B
------------
BK
NUM
How do I write a query to remove all records from table A, that are not in table B based on the two fields. So if Table A has a record where BK = 1 and NUM = 2, then it should look in table B. If table B also has a record where BK = 1 and NUM = 2 then do nothing, but if not, delete that record from table A. Does that make sense?
Any help is much appreciated.
You can do so
delete from tablea
where (BK,NUM) not in
(select BK,NUM from tableb)
using exists
delete from tablea a
where not exists
(select 1 from tableb where BK=a.BK and NUM = a.NUM)
Another alternative is to use an anti-join pattern, a LEFT [OUTER] JOIN and then a predicate in the WHERE clause that filters out all matches.
It's easiest to write this as a SELECT first, test it, and then convert to a DELETE.
SELECT t.*
FROM tablea t
LEFT
JOIN tableb s
ON s.BK = t.BK
AND s.NUM = t.NUM
WHERE s.BK IS NULL
The LEFT JOIN returns all rows from t along with matching rows from s. The "trick" is the predicate in the WHERE clause... we know that s.BK will be non-NULL on all matching rows (because the value had to satisfy an equality comparison, in a predicate in the ON clause). So s.BK will be NULL only for rows in t that didn't have a matching row in s.
For MySQL, changing that into a DELETE statement is easy, just replace the SELECT keyword with DELETE. (We could write either DELETE t or DELETE t.*, either of those will work.
(This is an illustration of only one (of several) possible approaches.)

Mysql only select row with existing parent

I have this query:
SELECT id,id1,title FROM tablename
LEFT JOIN tablename AS parent
ON tablename .id1 = parent.id
WHERE parent.id is NULL
What I try to achieve is that only rows are shown from which no parent exist.
Table layout and content
id id1(parent) title
1 0 parent
2 1 child1
3 1 child2
4 100 orphan
5 1 child3
6 1 child4
In this example I would query all but leave out the one which has no existing parent row (row 4, the orphan, parent 100 which does not exists in tablename).
This
SELECT child.id,child.id1,child.name
FROM table AS child --alias names, as column names would be ambiguous
LEFT JOIN table AS parent
ON table.id1 = parent.id
WHERE parent.id is NULL -- only no parent!
Shows the orphans. To get all non-orphans
SELECT child.id,child.id1,child.name
FROM table AS child
JOIN table AS parent -- JOIN takes care of getting only the records with parents
ON child.id1 = parent.id
Why does this work this way? LEFT JOIN is for joining tables, where we would like to receive rows of the left hand side table, where the right hand side table does not have a record that fulfills the join criteria. The columns pertaining to the right hand side table would all be NULL in that case. By using a simple JOIN, only those rows are shown from the first table, that have a record in the table on right hand side of the join.
Why did you get wrong result
The column names can get to be ambiguous when joining tables, and always do so when self-joining... You have to distinguish between them, by using alias names.
Ideas to consider
Maintainability. Keep this in mind, even for examples. Name your objects properly: table is not a descriptive name (and is a keyword too), use PERSON instead. For columns, id1 is not a descriptive name - use PARENT_ID instead...
Your query looks correct, except you need table aliases for the columns in the select:
SELECT table.id, table.id1, table.name
FROM table LEFT JOIN
table AS parent
ON table.id1 = parent.id
WHERE parent.id is NULL ;
The problem is that both table and parent have the same columns. The engine doesn't know which you really want without the table alias.
What I try to achieve is that only rows are shown from which no parent exist.
Surely this is the EXACT OPPOSITE of:
Mysql only select row with exisiting parent
The query in your question seems to exactly meet your requirement only rows are shown from which no parent exist
If you want the opposite of this , use an inner join and lose the where clause:
SELECT id,id1,name FROM table
INNER JOIN table AS parent
ON table.id1 = parent.id;
Try the following query:
SELECT id,id1,title
FROM table
WHERE id1 IS NULL OR id1 NOT IN(SELECT id FROM table);

LEFT JOIN (or similar) on a single-column table to get whether each row is in other table or not

Here's the situation. I have two sets of data. One is a list of all the "ticket" entries that my system uses – at least one per ID, but potentially more. I also have a separate list of just the IDs that have known hardware problems, which is a relatively small (but important) subset of the IDs. I've put this list into a super-simple table B, which is literally a single column with just those IDs.
I need a MySQL query that joins these two tables, so I get all of the entries from table A, each of which has another field added on that is a simple boolean: whether or not the same ID exists in table B.
So something like this:
SELECT * FROM `table_A` A
LEFT JOIN `table_B` B ON A.id=B.id
If B were a two-column table, and the second column (call it down) was simply true in every row, then I could check if down were true or null.
But since B has only a single column, no data is actually added to the result.
Is there any simple way (without having this otherwise completely unnecessary column in my database) to do this "join" operation, that will simply note whether or not the ID of a given entry in A also exists in B?
(adding another field to A that is up or down is also rather inefficient, since there are often many rows for a single ID and most IDs aren't going to be down anyway)
select
A.*,
case when B.ID is null then 0 else 1 end as myBoolean
from `table_A` A
left join `table_B` B on A.ID = B.ID
with the example below 'down' will not be null if the id exists in table_B
SELECT * , B.id as `down` FROM `table_A` A
LEFT JOIN `table_B` B ON A.id=B.id