SQL Select non intersecting elements from the super set - mysql

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.

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

get column value with ID as foreign key in recursion

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.

SQL: How do add a prefix to column names in a JOIN?

I have sql query like this
SELECT * FROM phlegm WHERE JOIN mucus ON phlegm.id = mucus.id JOIN snot ON phlegm.id = snot.id
The problem is those tables contain several columns with identical names.
For example all 3 tables contain the column named test
If I retrieve the result of the query in PHP, then I will only get one value named test ($query->get_result()->fetch_object()->test;), because the other two get overwritten.
Is there some way to edit that query so that it adds a prefix to all columns from a table? For example, column test from table mucus would be referenced in the query as mucus_test and column test from phlegm would be phlegm_test.
One way would be doing
SELECT phlegm.test as phlegm_test, mucus.test as mucus_test FROM phlegm...
But I have a LOT of columns and tables and it would make the query longer than the Great Wall of China if I had to name each field one by one.
So is there some way to add the prefix en masse?
SELECT *, phlegm.test as phlegm_test, mucus.test as mucus_test FROM phlegm...
Used aliasing to retrieve all values associated from all three tables. if you want to reference only specific column do so by using the alias_name.column_name instead of p.*, where * means all columns belonging to table that the alias is associated with( ie. p refers to phlegm).
SELECT p.*, m.*, s.*
FROM phlegm p
JOIN mucus m ON p.id = m.id
JOIN snot s ON p.id = s.id;
I removed the WHERE from your original query above, not sure why it was there.

Select from a table the ones that don't have a relationship with another table

The specific problem is listing the names of the teachers that never graded.
I have 'teachers' table with the columns 'Name' and 'ID'.
And 'grades' table with the column 'IDTeacher' and 'Grade'.
Don't get why this doesn't work:
Select Name from teachers where not exists(Select * from grades, teachers)
You can just join it with the grades table and use the ones where the join returns "null" for the right side:
SELECT
name
from
teachers t
LEFT JOIN
grades g
on
t.teacher = g.teacher
WHERE
ISNULL(g.teacher)
edit: Thought about a right join instead, but no, the right join might not work, if the teacher has no entry in the grades table. (Then you would miss him completely, even if he is in the teacher table)
You could also use WHERE IN for this:
SELECT
name
FROM
teachers
WHERE
name
NOT IN (SELECT name from grades)
BUT the MySQL Optimizer will rewrite this to exactly the correlated subquery #Gordon Linoff has written. Using WHERE NOT IN is just easier to read imho.
Your query does work, it just doesn't do what you think it should. The subquery creates a cartesian product between the two tables. If both tables have rows, then the cartesian product has rows and the where clause will always be true.
You can take this approach, but you need a correlated subquery:
Select Name
from teachers t
where not exists (Select 1 from grades g where g.idteacherid = t.id);
Note that this query only has one table in the subquery.
There are other ways to write this query, but this seems to be the approach you are heading in. And, not exists is a very reasonable approach.

mysql getting difference of 2 result sets

So I have two tables. One is called superIDs which has columns "superID BIGINT" and I have another one called mainIDs which has a column called "subid BIGINT". I know that mainIDS is a subset of superIDs. How can I see the rows that are ONLY in superID but not in mainIDs.
here is my attempt at a solution:
SELECT * FROM atlas_comparables.superIDs WHERE NOT EXISTS
(SELECT * FROM atlas_comparables.mainIDs);
However, this is returning me an empty set. Any help?
Try this
SELECT * FROM atlas_comparables.superIDs WHERE the_id_column NOT IN
(SELECT the_idcolumn_ofcomparable FROM tlas_comparables.mainIDs);
Note: the_id_column is in superIDs table
the_idcolumn_ofcomparable is in MainIdstable
If the ids only appear (at most) once in each table, then you can do this relatively easily with a left outer join:
select si.*
from atlas_comparables.superIDs si left join
atlas_comparables.mainIDs mi
on si.SuperID = mi.SubID
where mi.SubId is NULL;
If you are trying to compare all the columns (as except does in other databases), then you need a more complicated query, where you include all the columns on the on clause.