MySQL update query using WHERE and HAVING must have always multiple tables? - mysql

I want to update the price of brand 44 products
except ID's 17466 and 17467
considering only records from category 20 or category 22
UPDATE products_test
SET price=ROUND(price*1.06,0)
WHERE brand = 44 AND id NOT IN ('17466', '17467')
HAVING category = '20' OR category = '22'
I get an error on the HAVING line in the next query.
If I use SELECT the query runs ok.
I must use multiple tables or can go one table?
Probably I miss some operator or brackets
Im not an expert in MySQL

If the category is a column from products_test, you can add the condition to the WHERE-clause.
UPDATE products_test
SET price=ROUND(price*1.06,0)
WHERE brand = 44 AND id NOT IN ('17466', '17467') and category in ('20', '22')

Related

MySQL query conditional or subquery

I'm finding that SQL related questions are very difficult to express conversationally so please forgive me if this makes no sense.
I'm migrating data out of a CMS database to MySQL and I would like to simplify the data structure wherever possible. The current category scheme has 7 categories and has an item to category relationship setup as a many-to-many so a junction table is required.
It would be better setup as two one-to-many relationships so that an extra table is not required. The actual category setup that I need is as follows:
Category 1
Option 1
Option 2
Category 2
Option 3
Option 4
Option 5
Option 6
Option 7
Each item belongs to one value for Category 1, and one value for Category 2. This is the general form of the query I'm creating:
SELECT items.entry_id, categories.cat_id
FROM items
INNER JOIN categories
ON items.entry_id = categories.entry_id
WHERE items.item_type = 6
How would I add a conditional or sub query so that I got the results of the SELECT clause like:
SELECT items.entry_id, categories.cat_id1, categories.cat_id2
where the value of cat_id1 and cat_id2 are the values described above?
****Update****
I have made some progress getting the query I need (the tables are too complicated to post here for examples but here is a sample query):
SELECT exp_weblog_data.entry_id,
exp_weblog_data.field_id_27 AS Title,
exp_weblog_data.field_id_29,
exp_weblog_data.field_id_32,
exp_weblog_data.field_id_33,
exp_weblog_data.field_id_28,
exp_weblog_data.field_id_84,
exp_relationships.rel_child_id,
CASE WHEN exp_category_posts.cat_id = '15' OR exp_category_posts.cat_id = '16' THEN exp_category_posts.cat_id END as cat1,
CASE WHEN exp_category_posts.cat_id = '17' OR exp_category_posts.cat_id = '20' THEN exp_category_posts.cat_id END as cat2
FROM exp_weblog_data
INNER JOIN exp_relationships
ON exp_weblog_data.entry_id = exp_relationships.rel_parent_id
INNER JOIN exp_category_posts
ON exp_weblog_data.entry_id = exp_category_posts.entry_id
WHERE exp_weblog_data.weblog_id = 6
This gets me the two columns I want for Cat1 and Cat 2 but there are still two problems here - the inner join on exp_category_posts is resulting in 2 rows for each record where I only want one row for each value of entry_id. Secondly, in the case statements, I want to set a value of A if cat_id = 15 and B if cat_id = 16 but I can't seem to find the right syntax for this without getting errors.
I hope this clears things up a bit!
There is no reasonable way to avoid an extra table when setting up a many-to-many relationship.
Do not have multiple columns for multiple categories (cat_id1, cat_id2, ...).
Do not put multiple ids in a single column ("123,234,345").
Both of those lead to problems that are worse than having the mapping table.

SQL Update with concatenated data from another table

I'm keep getting lost in this one and struggling to find the right method. Hopefully someone out there might know of a good way of doing what I want to do.
I have two tables and I want to update one table using concatenated data from the other where the ids are the same. As an example....
Table1
ItemID CategoryID
1 20
1 30
1 40
2 10
3 40
3 20
4 10
4 20
Table2
ItemID CatIDs
1
2
3
4
I want to update Table2.CatIDs with all the Category IDs from Table1 where the ItemIDs match. It seems straightforward when I write it down like that but after trying Inner Joins, Sub Queries and so on as I've found online, I keep getting "You have errors in your SQL Syntax..."
I want Table2 to look something like
ItemID CatIDs
1 20,30,40
2 10
3 40,20
4 10,20
I've tried Inner Joins and also sub queries and the closest I've got without an error was this....
UPDATE Table2
SET Table2.CatIDs = Table2.CatIDs + ", " +
(SELECT CategoryID FROM Table1 WHERE Table2.ItemID = Table1.ItemID)
But it doesn't seem finished and all it done was update four rows with the same CatIDs and then give me the message
#1242 - Subquery returns more than 1 row
I'm sure someone out there will be able to see where I'm going wrong and point me in the right direction.
Thanks in advance
You should realize that table1 is the right way to store this information. It is called a junction or association table. Sometimes you need to do the concatenation for presentation purposes, but you need to keep the junction table for full flexibility.
You can do what you want using an update with join and group by:
UPDATE Table2 t2 JOIN
(SELECT t1.ItemId, GROUP_CONCAT(t1.CategoryId SEPARATOR ', ') as cats
FROM table1 t1
GROUP BY t1.ItemId
) tc
ON t2.ItemId = tc.ItemId
SET t2.CatIDs = tc.cats;
Try like below by using group_concat() you can get the , separated list and then join between the tables. But storing comma separated values is never a good idea.
update table2 t2
join
(
select ItemID,group_concat(CategoryID) as newcat
from table1 group by ItemID
) tab on t2.ItemID = tab.ItemID
set t2.CatIDs = tab.newcat

MySQL error updating a table using join

I am trying to update a table in a mysql database, and am getting a syntax error. It is a MyISAM table if that matters.
Here is the sql
UPDATE product SET price=(price*1.0909)
JOIN product_to_category ON product.product_id = product_to_category.product_id
WHERE category_id =6
OR category_id =1
OR category_id =2
My goal is to get a list of products from 3 specific categories (information from the *product_to_category* table) and increase the price by about 10%. The price is contained in the product table.
From what I see in the documentation I can use join in the update statement, and I have done similar queries in the past.
This is a production website, which currently has about 40,000 products. If needed I can do a php script that will loop through the products and do it one by one, but it seems like I should be able to do it directly from mysql.
Your statement is a little bit messed up. SET follows after JOIN which is part of the UPDATE clause.
UPDATE product
JOIN product_to_category
ON product.product_id = product_to_category.product_id
SET price = price * 1.0909
WHERE category_id IN (1,2,6)

Delete all but X newest entries in two joined MySQL tables

I'm experimenting with a query that I'll use for pruning two related mysql tables. I'll be using it to delete all but the most recent entries.
This query behaves exactly as I expect:
SELECT
O.id AS O_id,
T.id AS T_id
FROM
rt.ObjectCustomFieldValues AS O
LEFT JOIN rt.Transactions AS T
ON O.id = T.NewReference
WHERE
O.Disabled = 1
AND O.CustomField = 58
AND O.ObjectId = 202784
AND T.id NOT IN (
SELECT
id
FROM
(
SELECT
id
FROM
Transactions
WHERE
Field = 58
AND ObjectId = 202784
ORDER BY
Created DESC
LIMIT 5
) Test
)
For the rows containing ObjectId 202784, I get the ObjectCustomFieldValues ids and the Transactions ids for all but the most recent 5 items.
Now how do I turn this into a general query that I can run over all rows instead of specifying the ObjectId manually?
To summarize, for field id 58, I want to iterate all ObjectId values and for each one, delete all but the most recent ObjectCustomFieldValues and Transactions.
You can view schema details here:
https://github.com/bestpractical/rt/blob/stable/etc/schema.mysql#L112
and here:
https://github.com/bestpractical/rt/blob/stable/etc/schema.mysql#L328
If your structure is not INSERTing data with a UNIX_TIMESTAMP(), depending on your entire database structure order, this could be difficult. If you add a UNIX_TIMESTAMP() you can use ORDER BY correctly no matter what.

MySQL DELETE with JOIN on condition

I have 3 tables; products, variants, and stock {simplified}
PRODUCTS
id
name
discontinued (ENUM: 0 or 1)
etc
VARIANTS
id
product_id
colour
size
STOCK
id
variant_id
branch_id
When the user selects to discontinue the PRODUCT I set the discontinued flag to 1. That's fine, but I want to delete the PRODUCT and VARIANTS records altogether if there is no STOCK record of the product. Obviously I can do this using a SELECT query first in PHP but I would like to do it in one mySQL query. This is what I have so far, but it is returning an error from mySQL:
$query = "DELETE FROM prod_lines,
JOIN variants ON variants.lineid = prod_lines.id
WHERE prod_lines.id = '$lineid' AND
(SELECT COUNT(id) FROM stock WHERE stock.variantid = variants.id) = 0";
Can anybody out there help me come up with the right solution? Maybe there is a better way that doesn't even involve a subquery?
Thanks in advance
I assume that the product_line table in your query is the PRODUCTS table you describe in the beginning of your post.
DELETE prod_lines.* -- you must specify which table you are deleting from, because there are several tables in the FROM clause
FROM prod_lines
JOIN variants ON variants.lineid = prod_lines.id
LEFT JOIN stock ON stock.variantid = variants.id
WHERE prod_lines.id = #lineid -- your "$lineid" variable here
AND stock.id IS NULL; -- selects only items with no match in the "stock" table
http://sqlfiddle.com/#!2/40a21
Try something like this,the downside is though you have to have two php variables here and also an nested query that you may not be ok with
DELETE FROM (select COUNT(id) countstock FROM stock s,variants v WHERE s.variantid = v.id and v.productid='$lineid') prod
where prod.countstock>1 and prod.productid='$lineid'