Why is my column 'unknown' when using FULL JOIN - mysql

I'm learning sql and wanted to create my own tables to practise on. I found the following site: https://sqltest.net/
I created two tables to practise joins on. LEFT/RIGHT/INNER joins work fine with the sql statements i create but when i try to use FULL JOIN the following error appears:
Ouuuu snap '': Unknown column 'wizards.colours' in 'field list'
Is this something i'm doing wrong or a glitch with the website?
CREATE TABLE wizards
(
colours varchar(255),
numbers int,
symbols varchar(255)
);
INSERT INTO wizards
VALUES ('red','49','£'),
('blue','83','$'),
('blue','72','£'),
('purple','24','%'),
('orange','82','$'),
('white','67',NULL),
('blue','17','%'),
('black','12','%'),
('green','97','&'),
('grey','1','%'),
('red','6','£'),
('red','76','%');
CREATE TABLE warriors
(
colours varchar(255),
numbers int,
symbols varchar(255)
);
INSERT INTO warriors
VALUES ('orange','59','£'),
('purple','2','£'),
('white','11','%'),
('blue','78','%'),
('grey','56','$'),
('red','5','%'),
('orange','92',NULL),
('green','50','$'),
('orange','49',NULL),
('red','1','%');
my sql statement:
SELECT wizards.colours, warriors.numbers, wizards.numbers
FROM wizards
FULL JOIN warriors ON wizards.colours=warriors.colours
ORDER BY wizards.colours;

MySQL does not support full join:
You can use left + union + right join:
select * from (
SELECT wizards.colours, warriors.numbers as warriors_numbers, wizards.numbers as wizards_numbers
FROM wizards
LEFT JOIN warriors ON wizards.colours=warriors.colours
UNION
SELECT wizards.colours, warriors.numbers as warriors_numbers, wizards.numbers as wizards_numbers
FROM wizards
RIGHT JOIN warriors ON wizards.colours=warriors.colours
) T
ORDER BY colours;
Online demo at db<>fiddle

MySQL does not support FULL JOIN. But, the LEFT JOIN/RIGHT JOIN hack is not the best way to implement it. For instance, it doesn't handle duplicates correctly.
A better way is:
select cc.colours,
wa.numbers, wi.numbers -- whatever you want here
from ((select wi.colours
from wizards
) union -- on purpose to remove duplicates
(select wa.colours
from warriors wa
)
) c left join
wizards wi
on wi.colours = c.colours left join
warriors wa
on wa.colours = c.colours;
Even this is not 100% equivalent, because it does not handle NULL values correctly. However, it usually gets the intention right. You can fix the NULL handling by changing the ON conditions to use the NULL-safe comparison, on (wi.colours <=> c.colours>.
More importantly, you shouldn't need a FULL JOIN. They are almost never needed in a properly formed database.
In this case, that would mean that you have a colours table with correctly formed foreign key constraints. This is part of entity-relationship modeling and the right way to implement such relationships.

Related

SQL query optimization taking lot of time in execution

We have two tables one is properties and another one is property meta when we are getting data from one table "properties" , query only take less then one second in execution but when we are use join to get the data using bellow query from both tables its taking more then 5 second to fetch the data although we have only 12000 record in the tables , i think there is an issue in the sql query any help or suggestion will be appreciated.
SELECT
u.id,
u.property_title,
u.description,
u.city,
u.area,
u.address,
u.slug,
u.latitude,
u.longitude,
u.sync_time,
u.add_date,
u.is_featured,
u.pre_construction,
u.move_in_date,
u.property_status,
u.sale_price,
u.mls_number,
u.bedrooms,
u.bathrooms,
u.kitchens,
u.sub_area,
u.property_type,
u.main_image,
u.area_size as land_area,
pm7.meta_value as company_name,
pm8.meta_value as virtual_tour,
u.year_built,
u.garages
FROM
tbl_properties u
LEFT JOIN tbl_property_meta pm7
ON u.id = pm7.property_id
LEFT JOIN tbl_property_meta pm8
ON u.id = pm8.property_id
WHERE
u.status = 1
AND (pm7.meta_key = 'company_name')
AND (pm8.meta_key = 'virtual_tour')
AND (
(
( u.city = 'Delta'
OR u.post_code LIKE '%Delta%'
OR u.sub_area LIKE '%Delta%'
OR u.state LIKE '%Delta%')
AND country = 'Canada'
)
OR (
( u.city = 'Metro Vancouver Regional District'
OR u.post_code LIKE '%Metro Vancouver Regional District%'
OR u.sub_area LIKE '%Metro Vancouver Regional District%'
OR u.state LIKE '%Metro Vancouver Regional District%' )
AND country = 'Canada'
)
)
AND
u.pre_construction ='0'
GROUP BY
u.id
ORDER BY
u.is_featured DESC,
u.add_date DESC
Try adding this compound index:
ALTER TABLE tbl_property_meta ADD INDEX id_key (property_id, meta_key);
If it doesn't help make things faster, try this one.
ALTER TABLE tbl_property_meta ADD INDEX key_id (meta_key, property_id);
And, you should know that column LIKE '%somevalue' (with a leading %) is a notorious performance antipattern, resistant to optimization via indexes. (There's a way to create indexes for that shape of filter in PostgreSQL, but not in MariaDB / MySQL.)
Add another column with the meta stuff; throw city, post_code, sub_area, and state and probably some other things into it. Then build a FULLTEXT index on that column. Then use MATCH(..) AGAINST("Delta Metro Vancouver Regional District") in the WHERE clause _instead of the LEFT JOINs (which are actually INNER JOINs) and the really messy part of the WHERE clause.
Also, the GROUP BY is probably unnecessary, thereby eliminating extra sort on the intermediate set of rows.

Putting a working union query into a subquery causes JOIN syntax error

When I try to run the following query in Access 2016, I get a "Syntax error in JOIN operation" message.
Tables in use:
VISIB_BOMS is basically a self referencing hierarchy of part numbers in a Bill of Materials. (Similar to the classic example of an employee table where the employee can manager other employees.)
ztbl_IFSParts is just 1 column table of part numbers that I want to get the sub-component part numbers for.
The end goal is to have a single column table of all component parts from the parts from ztbl_IFSParts. I'll then use this list to get further info from JOINs to other tables.
SELECT *
FROM
(
/* CODE BETWEEN HERE WORKS */
(
SELECT DISTINCT aa0.PartNo AS PartNo
FROM ztbl_IFSParts AS aa0
)
UNION ALL
(
SELECT DISTINCT b0.COMPPARTNO AS PartNo
FROM
(
SELECT DISTINCT aa0.PartNo AS PartNo
FROM ztbl_IFSParts AS aa0
) AS ab0
LEFT JOIN VISIB_BOMS AS b0
ON ab0.PartNo = b0.ASSYPARTNO
)
/* CODE BETWEEN HERE WORKS */
)
If I run the code between the comments on its own it works fine, only when I try to do any SELECT operations on it, it throws an error.
Hope it's enough info to run with.
Removing the brackets around the two queries either side of the UNION ALL solved this.

Combining EXISTS and LEFT JOIN

I need some help combining two queries I wrote( I do not know if it is possible to do it or not). But first let me show you the table and exaplin it so there are no ambiguous angles here.
This is the table I have (PS : I do not know how to make decent looking tables in StackOverflow even though I researched it, and tried to use Senseful solutions so please excuse the image) :
Main Table
The first query I have is the following :
SELECT *
FROM Dropship As t1
WHERE t1.HUB_SO_GOODS_ISSUE_DATE IS NULL
AND EXISTS (SELECT * FROM Dropship t2
WHERE t2.LE_PO = t1.LE_PO
AND t2.HUB_SO_GOODS_ISSUE_DATE IS NOT NULL);
This query gives me all orders that have not have been fully processed. So with the table I have it gives me the orders (LE_PO) 300 and 500 like in the following image :
result from first query
Another query I use is the left join one :
SELECT Dropship.*, Notes_Replenishment.*
FROM Dropship LEFT JOIN Notes_Replenishment ON Dropship.LE_PO = Notes_Replenishment.LE_PO;
The notes_replenishment table has all the orders (LE_PO) but also comments put in by a user. What I would like to do is to incorporate the left join in to the first query so that it gives me the result (see above) but also the comments from the Notes_replenishment table however I get errors when I tried doing it by myself.
Could somebody give me some pointers on how to combine the two queries?
Thank you all in advance!
SELECT *
FROM Dropship As t1
LEFT JOIN
Notes_Replenishment
ON t1.LE_PO = Notes_Replenishment.LE_PO
WHERE t1.HUB_SO_GOODS_ISSUE_DATE IS NULL
AND EXISTS
(
SELECT *
FROM Dropship t2
WHERE t2.LE_PO = t1.LE_PO
AND t2.HUB_SO_GOODS_ISSUE_DATE IS NOT NULL
)

Multiple joins involving same table produces "column doesn't exist" error - MySQL

I'm new to joins and I'm sure this is ridiculously simple. If I remove one join in the query the remainder of the query works regardless of which join I remove. But as shown it gives the error saying the column doesn't exist. Any pointers?
select
loc_carr.address1 as carr_addr1,
loc_cust.address1 as cust_addr1
from db_name.carrier, db_name.customer
join db_name.location as loc_carr on vats.carrier.location_id=loc_carr.location_id
join db_name.location as loc_cust on vats.customer.location_id=loc_cust.location_id
thanks
I'll take a guess that there is a column named something like carrier_id that can be used to join the carrier and customer tables. Given that assumption, try this:
select
loc_carr.address1 as carr_addr1
, loc_cust.address1 as cust_addr1
from vats.carrier as a
join vats.customer as b
on b.carrier_id=a.carrier_id
join vats.location as loc_carr
on loc_carr.location_id=a.location_id
join vats.location as loc_cust
on loc_cust.location_id=b.location_id
Notice the use of aliases for the table references to make things easier to read. Also note how I'm using explicit SQL join syntax (instead of listing tables separated by commas).
#Bob Duell has the solution for your problem. To understand better why this error is produced, notice that in the FROM clause, you "join" tables using both explicit JOIN syntax and the implicit joins with comma: , which is (almost) equivalent to a CROSS JOIN. The precedence however of JOIN is stronger than the comma , operator. So, that part is parsed like this:
FROM
( db_name.carrier )
,
( ( db_name.customer
JOIN db_name.location AS loc_carr
ON carrier.location_id = loc_carr.location_id -- this line
) -- gives the error
JOIN join db_name.location AS loc_cust
ON customer.location_id = loc_cust.location_id
)
In the mentioned line above, the vats.carrier.location_id throws the error, as there is no carrier table in that scope (inside that parenthesis).

MYSQL and IN in requests

I am a beginner when it comes to using mysql queries embedded inside other mysql queries using the IN statement.
I currently have this query:
SELECT DISTINCT BorName
FROM Borrower
WHERE BorId IN (
SELECT Borrower.BorId
FROM Loan
WHERE Loan.BcId IN (
SELECT BookCopy.BcId
FROM BookCopy
WHERE BookCopy.BtId In (
SELECT BookTitle.BtId
FROM BookTitle
WHERE BookTitle.PubId In (
SELECT Publisher.PubId
FROM Publisher
WHERE `PubName` = CONVERT( _utf8 'Methuen' USING latin1 ) COLLATE latin1_swedish_ci
)
)
)
);
I am basically trying to find out if a borrower has borrowed a book from the publisher Methuen. I just cant seem to work out what is wrong, I have gone through each individual statement and they all seem to work just not the overall request with all of the IN statements.
Can anyone spot what is wrong?
Like suggested, JOINs are a much cleaner, and likely a more efficient way to do this query as opposed to nested INs:
SELECT DISTINCT b.BorName
FROM
Borrower b
JOIN Loan l ON l.BorId = b.BorId
JOIN BookCopy bc ON bc.BcId = l.BcId
JOIN BookTitle bt ON bt.BtId = bc.BtId
JOIN Publisher p ON p.PubId = bt.PubID
WHERE
p.PubName = CONVERT( _utf8 'Methuen' USING latin1 ) COLLATE latin1_swedish_ci
Additionally, I think there was a problem in your first sub-query:
SELECT Borrower.BorId
FROM Loan
WHERE Loan.BcId IN...
I believe should have been:
SELECT Loan.BorId
FROM Loan
WHERE Loan.BcId IN...
Replace all the IN by =
Obviously using joins will be much cleaner.
I am not sure if MySQL supports the with clause but in SQL Server you are able to use something called a Common Table Expression. This is a ANSII SQL spec that should be easily determined.
Psuedo:
With
someMadeUpTableAlias AS
(
SELECT...
)
SELECT ...
FROM
OutsideTable AS A
someMadeUpTableAlias AS B ON (A. = B.)
I have been making a large effort to take advantage of the CTE's because of the readability inherently not there with subqueries. You may want to take a look at the side effects as behind the scenes it would be creating a temporary table and mysql may have some performance hits associated. Easiest way to tell is clear your query cache and run it both ways.