I use MySql, when running below query, I find it acts differently in two box, could any one help me out?
The code is here:
SELECT *
FROM `product` AS `e`
WHERE e.id NOT IN((SELECT `product_id` FROM `sales`))
In one box, it works well and returns the result. In the other box, it shows the error:
[Err] 1242 - Subquery returns more than 1 row
And it works well in both box if remove one pair of (), as below:
SELECT *
FROM `product` AS `e`
WHERE e.id NOT IN(SELECT `product_id` FROM `sales`)
Could anyone tell me the reason, i.e. related to server setting? Can I fix this without modify the sql statements?
The data;
(SELECT `product_id` FROM `sales`)
is treated as the first item in the list to be used by 'NOT IN'.
This must be a single value, so you get the error because multiple rows are returned.
Related
I am using laravel framework for developing API's ,i have one query that is executed without where condition without any error i need to execute with where condition but it's throwing an error
query
select count(*) as aggregate
from `users`
left join `books` on `books`.`book_id` = `books`.`id`
where `access_id` = 5054
SQL Error [1052] [23000]: Column 'access_id' in where clause is
ambiguous
after searching google i got something we have to specify reference of a table name , i added reference name like this where users.access_id =5054 but it's throwing an error like unknown column but in my db i have that column in both users and books table
The problem is its consider as a column so that's why syntax error is coming,try following way it will resolve your problem
select count(*) as aggregate
from `users`
left join `books` on `books`.`book_id` = `books`.`id`
where `users`.`access_id` = 5054
I am tying to run an update query with a subquery against a MySQL database using ruby. I am using ruby 1.9.3 and rails 4.1.
The query I am trying to create is as below:
UPDATE `items`
SET
`items`.`status_id` = 12
WHERE
`items`.`id` IN (SELECT DISTINCT
`items`.`id`
FROM
`items`
LEFT OUTER JOIN
`statuses` ON `items`.`status_id` = `statuses`.`id`
LEFT OUTER JOIN
`resources` ON `items`.`resource_id` = `resources`.`id`
WHERE
`statuses`.`title` LIKE 'On Loan'
AND `items`.`duedate` < '2015-04-24'
AND `items`.`return_date` IS NULL
ORDER BY `items`.`duedate`)
I can produce this query in ruby using AREL with the code shown below:
# Declare Arel objects
i = Item.arel_table
s = Status.arel_table
r = Resource.arel_table
# This is the AREL query that returns the data
overdues = i.project(i[:id]).
join(s, Arel::Nodes::OuterJoin).on(i[:status_id].eq(s[:id])).
join(r, Arel::Nodes::OuterJoin).on(i[:resource_id].eq(r[:id])).
where(s[:title].matches("On Loan").
and(i[:duedate].lt(DateTime.now.to_date)).
and(i[:return_date].eq(nil))
).
order(i[:duedate])
# Note: You can't chain distinct, otherwise "overdues" becomes a string with the value "DISTINCT".
overdues.distinct
# This creates the update...
u = Arel::UpdateManager.new i.engine
u.table(i)
u.set([[i[:status_id], 10]]).where(i[:id].in(overdues))
This does not work and returns an error message:
ActiveRecord::StatementInvalid: Mysql2::Error: You can't specify target table 'items' for update in FROM clause:
I tried using AR "update_all" but it produces the same SQL and hence the same error.
Item.where(i[:id].in(overdues)).update_all(:status_id => (Status.find_by(:title => "Overdue").id))
Having done some research I have found that you cannot run a update with a subquery that references the table you want to update in MySQL. I have seen a number of posts on this site and the wider internet that detail work arounds.
One suggestion says that the update should use a join instead of a sub query. Having looked at the code behind the update manager it has no "join" so I can't do that.
Another says run this in two parts but I can't see how to because AREL and AciveRecord both chain actions.
The only way I can see of doing this is by aliasing the table and adding an additional select (see below). This isn't great but it would be useful to see if it is possible to do.
UPDATE `items`
SET `status_id` = 10
WHERE `items`.`id` IN (
SELECT x.id
FROM
(SELECT DISTINCT `items`.`id`
FROM `items`
LEFT OUTER JOIN `statuses` ON `items`.`status_id` = `statuses`.`id`
LEFT OUTER JOIN `resources` ON `items`.`resource_id` = `resources`.`id`
WHERE `statuses`.`title` LIKE 'On Loan'
AND `items`.`duedate` < '2015-04-24'
AND `items`.`return_date` IS NULL
ORDER BY `items`.`duedate`) x
);
If I can't get this to work I could adopt two other approaches:
1) I could just hard-code the SQL but I want to use ActiveRecord and reference the models to keep it database agnostic.
2) The other way is to return an instance of all the records and loop through them doing individual updates. This will have a performance issue but I can accept this because its a background job that won't be updating more than a handful of records each day.
Update
I have the AREL query below that produces the subquery in the format I need.
x = Arel::Table.new('x')
overdues = Item.select(x[:id]).from(
Item.select(Item.arel_table[:id]).where(
Status.arel_table[:title].matches("On Loan").and(
Item.arel_table[:duedate].lt(DateTime.now.to_date).and(
Item.arel_table[:return_date].eq(nil))
)
).joins(
Item.arel_table.join(Status.arel_table, Arel::Nodes::OuterJoin).on(
Item.arel_table[:status_id].eq(Status.arel_table[:id])
).join_sources
).joins(
Item.arel_table.join(Resource.arel_table, Arel::Nodes::OuterJoin).on(
Item.arel_table[:resource_id].eq(Resource.arel_table[:id])
).join_sources
).order(Item.arel_table[:duedate]).uniq.as('x')
)
Sadly it returns an error when I use it in my update statement.
TypeError: Cannot visit Item::ActiveRecord_Relation
Having revisited this question I am at the conclusion that it's not possible to do this because of a limitation with MySQL:
ActiveRecord::StatementInvalid: Mysql2::Error: You can't specify target table 'items' for update in FROM clause:
It should be possible to do with other databases (although I haven't tested that).
I could create a temporary table, which is the copy of the original table, reference that and then drop the temporary table like this post suggests:
http://richtextblog.blogspot.co.uk/2007/09/mysql-temporary-tables-and-rails.html. That seems a lot of overhead to do a simple subquery.
What I am going to do is find all the ID's and loop through them and update the records that way (using a simple find and update). This has an overhead but it should only be updating a handful of records each run (no more than 100). The update will be running as a scheduled job outside user working hours so it won't impact performance.
I still find it bizarre that in all other flavours of SQL I have never encountered this problem before. Still you live and learn.
UPDATE:
Since updating my version of MySQL the select statement now works. I had to take out the order by for it to work.
ORDER BY `items`.`duedate`
I am now using version: 5.7.19.
I am trying to make a delete from joined same table like this:
DELETE FROM `sp10_seo_url` AS sp1 JOIN
(
SELECT seo_url_pk, COUNT(*) AS maxc
FROM `sp10_seo_url`
GROUP BY seo_url_entity_type, seo_url_entity_id, seo_url_language_fk
HAVING maxc > 1
) AS sp2
ON sp1.seo_url_pk = sp2.seo_url_pk
However I am getting a mysql error
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'AS sp1 JOIN ( SELECT seo_url_pk, COUNT(*) AS maxc FROM `sp10_s' at line 1
And I am not sure at all where the error is. The inner query runs just fine and returns the expected set of results. The "ON" keys are properly named (same since we are talking about the same table).
I guess the idea of the query is pretty clear (clean the table of different rows have the same set of values for the three "group by" columns. Is there another way to do this?
Thanks!
you can "cheat" mysql with a double indirection (as explained here Deleting a row based on the max value):
delete from `sp10_seo_url`
where seo_url_pk in (
select seo_url_pk from (
SELECT seo_url_pk
FROM `sp10_seo_url` sp1,
(
SELECT seo_url_entity_type, seo_url_entity_id, seo_url_language_fk
FROM `sp10_seo_url`
GROUP BY seo_url_entity_type, seo_url_entity_id, seo_url_language_fk
HAVING count(*) > 1
) sp2
where sp1.seo_url_entity_type = sp2.seo_url_entity_type
and sp1.seo_url_entity_id = sp2.seo_url_entity_id
and sp1.seo_url_language_fk = sp2.seo_url_language_fk
) t
);
http://sqlfiddle.com/#!2/899ff5/1
I know there is more than one question out there that matches this, but I am relatively new to mysql, and I can't seem to make this work using sub quests or the USING key word, plus I find the mysql on line docs a complete mystery.
I started trying to build my DELETE query using a SELECT query as my base and was able to get all the rows that I wanted to delete:
select *
from writings_tags_link
join writing_tags on writing_tags.id = writings_tags_link.tag_id
where writing_tags.tag = 'tag one'
and then just replaced select all with DELETE so:
delete
from writings_tags_link
join writing_tags on writing_tags.id = writings_tags_link.tag_id
where writing_tags.tag = 'tag one'
I gather from both the error message and from other similar posts that you can't use 'ON' to join tables in a delete query, you have to use USING or a sub query. The query I built with USING returns a really strange error, first the query:
DELETE
FROM writings_tags_link
USING writing_tags_link INNER JOIN writing_tags
WHERE writing_tags.id = writings_tags_link.tag_id
AND writing_tags.tag ='tag one'
error:
#1109 - Unknown table 'writings_tags_link' in MULTI DELETE
This table does exist, obviously, my original select query returned the desired results. Any help / explanation would be so very appreciated!
Please keep in mind, I'm only trying to delete the data in the linking table.
Your information is incorrect about requiring the use of the USING keyword in DELETE syntax when using JOINs - the documentation provides examples in the multi-delete section:
DELETE wtl
FROM WRITINGS_TAGS_LINK wtl
JOIN WRITING_TAGS wt ON wt.id = wtl.tag_id
WHERE wt.tag = 'tag one'
hey, i have 2 version of mysql on windows 5.1.39-community and on linux 5.1.39-log
i execute a query:
SELECT `o`.`idOffer`,
`o`.`offer_date`,
`p`.`factory`,
`c`.`short` AS `company`,
`s`.`name` AS `subcategory`,
`ct`.`name` AS `category`,
count( (select count(1) from product where idProduct=idOffer group by idOffer) ) as b
FROM `Offer` AS `o`
LEFT JOIN `Product` AS `p` ON o.idOffer = p.idOffer
LEFT JOIN `company` AS `c` ON o.company = c.id
LEFT JOIN `Subcategory` AS `s` ON s.idSubcategory = o.idSubcategory
LEFT JOIN `Category` AS `ct` ON ct.idCategory = s.idCategory
WHERE (o.idOffer = p.idOffer) GROUP BY `o`.`idOffer`
on windows it works as it suppose, but on linux it says:
ERROR 1242 (21000): Subquery returns more than 1 row
is it any way to get it worked on linux without any mysql updates/downgrades ?
Since your SQL "as b" columnResult is based specifically on a SQL, and the WHERE clause of the of the idOffer already qualifies and SHOULD be the same, I would remove the group by of this columnar element. I can only assume there might be some white-space data or other that is falsely getting included and "ID1" is different than "ID1 " is getting falsely interpretted.
No idea if this has anything to do with it, but Linux MySQL tables are case sensitive while Windows tables are not (because of the filesystem, I suspect), anyway, you have Product and product and that will cause some problems.
Don't know if it really is the cause of the problem in your question, but it is a wall you may end up flying smack into and I thought it should be brought up.