Mysql - Alias in Left Outer Join giving error - mysql

I have been looking at examples in Stackoverflow but none have given me results, I have a query in which "select" there is an alias that I then need to use with a "LEFT OUTER JOIN" to compare it with the column of another table but when I execute it it generates an error of unknown column, I have been reading that a second JOIN is required but I do not know how to do it.
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(embed, '/', -2), '"', 1) as idvideo, embed, thumbnail, title,
MATCH(title, tags, category) AGAINST('peruvian food') as score
FROM peruvian_food
LEFT OUTER JOIN peruvian_food_del ON (peruvian_food.idvideo = peruvian_food_del.id_video_del)
WHERE MATCH(title, tags, category) AGAINST('peruvian food' IN BOOLEAN MODE)
AND peruvian_food_del.id_video_del IS NULL
LIMIT 30
I am getting the following error:
#1054 - Unknown column 'idvideo' in 'on clause'

The error is saying that the table peruvian_food does not contain a column named idvideo.
If we are attempting to reference the expression in the SELECT list that is assigned the alias idvideo, that reference is not allowed in the ON clause within the same SELECT. Even if a reference like that was allowed, we wouldn't qualify it with the peruvian_food. table name; there isn't a column named idvideo in that table.
Simplest workaround is to repeat the expression used in the SELECT list:
ON ( SUBSTRING_INDEX(SUBSTRING_INDEX(peruvian_food.embed, '/', -2), '"', 1) = ...
If we need to reference the idvideo alias, we would need to use an inline view, so that the column name was from a derived table.
We're just guessing at the specifiction... what it is we're trying to achieve. (I'm not even sure there was a question being asked; reads more like a status report than a question, so we're also just guessing at what question is being asked.)

Related

SELECT SUBSTRING(column) ... HAVING SUBSTRING(column) cause unknown column error in mysql

SELECT SUBSTRING(column, ..)
FROM someTable
GROUP BY SUBSTSRING(column, ..)
HAVING SUBSTRING(column, ..) IS NULL;
The query written above resulted in an error. But,
SELECT SUBSTRING(column, ..) AS otherName
FROM someTable
GROUP BY SUBSTSRING(column, ..)
HAVING otherName IS NULL;
The query written above is OK. What causes this result?
Read mysql doc here
from doc: The SQL standard requires that HAVING must reference only columns in the GROUP BY clause or columns used in aggregate functions. However, MySQL supports an extension to this behavior, and permits HAVING to refer to columns in the SELECT list and columns in outer subqueries as well.

How to find rows in SQL that end with the same string?

I have a question similar to the one found here: How to find rows in SQL that start with the same string (similar rows)?, and this solution works in MySQL 5.6 but not 5.7.
I have a database (t) with multiple columns, the important ones being id and filepath, and what I am trying to accomplish is retrieving all the file paths which have the same last 5 characters. The following works in MySQL5.6, and the second SELECT works fine in 5.7:
SELECT id, filepath FROM t
WHERE SUBSTRING(filepath, -5) IN
(
SELECT SUBSTRING(filepath, -5)
FROM t
GROUP BY SUBSTRING(filepath, -5)
HAVING COUNT(*) > 1
)
But when I try to run it on 5.7 I get the error
Expression #1 of HAVING clause is not in GROUP BY clause and contains
nonaggregated column 't.filepath' which is not functionally dependent on
columns in GROUP BY clause; this is incompatible with
sql_mode=only_full_group_by
Sample data:
id filepath
1 /Desktop/file1.txt
2 /Desktop/file2.txt
3 /Desktop/file1.txt
and I would want to return the rows with id 1 and 3. How can I fix this for MySQL5.7?
EDIT: Also can anybody point me in the right direction for the SQL to remove the duplicates? So I would want to remove the entry for id 3 but keep the entry for id 1 and 2.
Please read the mysql documentation on the subject GROUP BY and sql_mode only_full_group_by (like your error message says):
https://dev.mysql.com/doc/refman/5.7/en/group-by-handling.html
I think changing the inner query to this might fix the problem:
SELECT SUBSTRING(filepath, -5) AS fpath
FROM t
GROUP BY fpath
HAVING COUNT(fpath) > 1
Edit:
As to your question of why adding the "AS fpath" works:
Adding the alias "fpath" is just a clean way to do this. The point of ONLY_FULL_GROUP_BY is that each field you use in the SELECT, HAVING, or ORDER BY must also be in the GROUP BY.
So I added the fpath-alias for multiple reasons:
For performance: The query you wrote had SUBSTRING(filepath, -5) twice, which
is bad for performance. Mysql has to execute that SUBSTRING call twice,
while in my case it has to do it only once (per row).
To fix the group-by issue: You had COUNT() in the having, but "" was not in your GROUP BY statement (I'm not even sure whether that would be possible). You had to count "something", so since "fpath" was in your SELECT and in your GROUP BY, using that as your COUNT() would fix the problem.
I prefer not to put subqueries in an IN() predicate because MySQL tends to run the subquery many times.
You can write the query differently to put the subquery in the FROM clause as a derived table. That will make MySQL run the subquery just once.
SELECT id, filepath
FROM (
SELECT SUBSTRING(filepath, -5) AS suffix, COUNT(*) AS count
FROM t
GROUP BY suffix
HAVING count > 1
) AS t1
JOIN t AS t2 ON SUBSTRING(t2.filepath, -5) = t1.suffix
This is bound to do a table-scan though, so it's going to be a costly query. It can't use an index when doing a substring comparison like that.
To optimize this, you might create a virtual column with an index.
ALTER TABLE t
ADD COLUMN filepath_last VARCHAR(10) AS (SUBSTRING_INDEX(filepath, '/', -1)),
ADD KEY (filepath_last);
Then you can query it like this, and at least the subquery uses an index:
SELECT id, filepath
FROM (
SELECT filepath_last, COUNT(*) AS count
FROM t
GROUP BY filepath_last
HAVING count > 1
) AS t1
STRAIGHT_JOIN t AS t2 ON t2.filepath_last = t1.filepath_last
The solution that ended up working for me was found here: Disable ONLY_FULL_GROUP_BY
I ran SELECT ##sql_mode then SET ##sql_mode = followed by a string containing all the values returned by the first query except for only_full_group_by, but I'm still interested in how this is to be accomplished without changing the SQL settings.

Concatenation is not working in select query

We are fetching list of ordered products from database including join with order table.
We want to list all orders with how many quantity of products order in each order on the basis of passed product ids. We also want to display customer name which was placed the order. So, as per our knowledge we have created an query to get items as:
SELECT
`main_table`.*,
`order`.*,
SUM(main_table.qty_ordered - main_table.qty_canceled) AS `custom_qty`,
SUM(main_table.row_total) AS `custom_row_total`,
SUM(main_table.tax_amount) AS `tax_amount`,
SUM(main_table.hidden_tax_amount) AS `hidden_tax_amount`,
SUM(main_table.discount_amount) AS `discount_amount`,
CONCAT(order.customer_firstname, ' ' ,order.customer_middlename, ' ', order.customer_lastname) AS full_name
FROM `sales_flat_order_item` AS `main_table`
INNER JOIN `sales_flat_order` AS `order` ON main_table.order_id=order.entity_id
WHERE (((((main_table.product_id = '902') OR (main_table.product_id = '903') OR (main_table.product_id = '904'))))) AND (main_table.store_id = '1') AND (CONCAT(order.customer_firstname, order.customer_middlename, order.customer_lastname) like '%rag%')
GROUP BY `main_table`.`sku`
All the aggregate functions used in above query working fine except concat(). Every time we will get the value of full_name column as NULL even we have name the corresponding concatenated columns.
Please any one helps me to figure out why this is not working. Are we doing something wrong in the above query?
Thanks in advance.
As CONCAT() returns NULL if any argument is NULL I'm guessing maybe one of the three arguments is NULL?
Try using the CONCAT_WS() function instead (as you use separators anyway) which skips null values.
CONCAT_WS(' ', order.customer_firstname, order.customer_middlename, order.customer_lastname) AS full_name
See the documentation for more information.
On a side note: you might want to look into how you can use table aliases to shorten the query text and make it more readable.
Are you sure EVERY column has an value? (Middlename?)
The MYSQL manual says:
SELECT CONCAT('My', NULL, 'QL')
-> NULL

having condition on result of a subquery in mysql

i am trying to run a query like this
SELECT a, b , c, (SELECT INNULL(x,y)) as mycol WHERE mycol < 400 ;
BUt it gives the error
#1054 - Unknown column 'mycol' in 'where clause'
What would be the right way to do this?
Thanks.
It's so in MS SQL, so I assume, that the same problem is in MySQL.
Try to change WHERE to HAVING. WHERE clause doesn't see your renamed columns.
HAVING is working the same way as WHERE, like (mycol < 400 AND a > 5).
GROUP BY should be before HAVING.
Check the examples in the link.
http://www.databasejournal.com/features/mysql/article.php/3469351/The-HAVING-and-GROUP-BY-SQL-clauses.htm
#hgulyan I doubt your answer. It is not the renaming that prevents one from using WHERE clause, rather it is the subquery. So lets say I have a query:
SELECT id as ID FROM user WHERE ID > 10;
This is going to work perfectly fine.
Now lets say I have one more query:
SELECT name, (SELECT id FROM user_detail WHERE user_id = 20) as ID FROM user WHERE ID > 19;
This particular query will produce error as:
Unknown column ID
So, it's about using subquery and column aliases and not just column aliases.
Thus in this case you will have to use HAVING instead of WHERE.

mysql 'Unknown column' error

What is wrong with this:
SELECT *,
GROUP_CONCAT(DISTINCT w.tag_word ORDER BY w.tag_word ASC SEPARATOR ' ') AS tags,
MATCH (title, description, tags) AGAINST ('london') AS score
FROM article G
JOIN tag_index I ON G.article_id = I.tag_target_id
JOIN tag_word W ON I.tag_word_id = W.tag_word_id
WHERE I.tag_type_id = 1 AND MATCH (title, description, tags) AGAINST ('london')
GROUP BY G.article_id
I get the error 'Unknown column 'tags' in 'field list''
UPDATE:
Thank you Parrots for pointing out that I need the HAVING clause. I still can not figure out how to implement it. I can only guess it can not be done in one query and needs to be a subquery.
Since "tags" a value you're creating using GROUP_CONCAT you need to use the having clause. Whenever you want to apply a condition to stuff after the grouping, use having. It works the same as where just after the grouping.
Where in your code example is trying to be applied to filter the results from article that will eventually be grouped to build things like "tags".