Update the mysql column with merge of two ROW values - mysql

I have a table user_brand in my database, which stores information about brand which user buy. Assuming that my table has no dependency on another table, table looks like this:
User_ID | Brand | meta_key
---------+--------------+-------------
1 | Killer | Name
1 | Lewis | Name
1 | Pepe | Name
1 | Cloth | Product
2 | Samsung | Name
2 | Motorolla | Name
2 | CellPhone | Product
3 | Acer | Name
3 | Laptop | Product
Now I want my brand column to update so that the output will be like below, and if meta_key is duplicated it will be fine for me, I have not much concern about that.
User_ID | Brand
---------+-----------------------
1 | Killer, Lewis, Pepe
2 | Samasung, Motorolla
3 | Nisaan
I achieved to get the output in select query and i.e
SELECT User_ID, GROUP_CONCAT(Brand)
FROM user_brand
WHERE meta_key = "Name"
GROUP BY User_Id
But tried so many way to update that particular column but failed.
Some tried query is:
UPDATE user_brand
SET Brand = (SELECT max
FROM
(SELECT GROUP_CONCAT(Brand) AS max
FROM user_brand
WHERE meta_key = "Name"
GROUP BY User_id) AS t)
UPDATE user_brand AS t1
JOIN
(SELECT
GROUP_CONCAT(brand) AS max
FROM user_brand
WHERE meta_key = "Name"
GROUP BY User_id) AS t2
SET t1.Brand = t2.max
Any help, it will be highly appreciated.

Try below - You've to add ON Clause
UPDATE user_brand t1
JOIN
(SELECT User_id,GROUP_CONCAT(brand) as max FROM user_brand where meta_key = "Name"
group by User_id
) AS t2 on t1.user_id=t2.user_id
SET t1.Brand = t2.max

Related

extended update in mysql

I have a table named 'products' and another table named 'rates' that has one to many relation with 'products' table. For each product i have two rows in 'rates' table that i want update one boolean column named 'index' to 1 for each 'product' in 'rates' table.
i used this query :
UPDATE ( SELECT
products.id AS productId,
products.name ,
X.`index` AS `index`,
x.id AS rateId,
x.price, x.discount
FROM products JOIN ( SELECT rates.*
FROM rates
) AS x
WHERE products.id = x.product_id
GROUP BY products.id
) AS y
SET y.index = 1
but id got this error massage:
SQL Error (1288) the target table y of the update is not updatable
i'm new in mysql and i don't know where is my mistake.Thank you for helping
Products Table
| id | name
| 1 | chair
| 2 | bench
Rates Table
| id | product_id | index | value
| 1 | 1 | 0 | xx ==> index = 1
| 2 | 1 | 0 | yy
| 3 | 2 | 0 | zz ==> index = 1
| 4 | 2 | 0 | tt
i want update index column for each product in rates to 1
It looks like you want to update the "first" row in rates for each product_id. If so, you can self-join the table with an aggregate query that computes the minimum id per product_id:
update rates r
inner join (select product_id, min(id) id from rates group by product_id) r1
on r1.id = r.id
set r.index = 1

MySQL how to select first row each group with count

I have a table like this (simplified version):
+------+-------+-----+--------------+-----+
| id | name | age | company.name | ...
+------+-------+-----+--------------------+
| 1 | Adam | 21 | Google | ...
| 3 | Peter | 20 | Apple | ...
| 2 | Bob | 20 | Microsoft | ...
| 9 | Alice | 18 | Google | ...
+------+-------+-----+--------------------+
I need groups data with counting rows by any one column. And I need to get first row in each group. User select which column will be used to group.
If user select column age to group then results:
+------+------------+-------+
| id | group_name | count |
+------+------------+-------+
| 9 | 18 | 1 |
+------+------------+-------+
| 2 | 20 | 2 |
+------+------------+-------+
| 1 | 21 | 1 |
+------+------------+-------+
Column to group may be numeric or string.
Currently I does it by this query:
SELECT id, group_name, users_name, count(id) as count FROM (
SELECT persons.id as id, company.type as group_name, users.name as users_name
FROM persons
LEFT JOIN company on company.id = persons.company_id
LEFT JOIN position on position.id=persons.position_id
...
LEFT JOIN source on source.id=persons.source_id
WHERE ...
ORDER BY if(company.type = '' or company.type is null,1,0) ASC,
company.type ASC, IF(persons.status = '' or persons.status is null,1,0) ASC,
persons.status ASC, persons.id
) t1 GROUP BY group_name
but with new version mysql this SQL stoped works I think that order is ignored in sub-select.
I know that similar topics was wroted, but proposed solutions not working with my query. I have to join many tables, add multiple conditions and use cascade order and then select first row from each group. I will be very happy if solution will be optimised for performace.
---- EDIT ----
Proposed solution:
SQL select only rows with max value on a column
which suggest to use MAX() and GROUP BY not working well. For two reason
If grouped column include string, then query return not first row, but last row in each group.
If my dataset has a cascade order, I can not use MAX in a few columns at the same time.
I created sqlfiddle which include exact example.
http://sqlfiddle.com/#!9/23225d/11/0
-- EXAMPLE 1 - Group by string
-- base query
SELECT persons.*, company.* FROM persons
LEFT JOIN company ON persons.company_id = company.id
ORDER BY company.name ASC, company.id ASC;
-- grouping query
SELECT MAX(persons.id) as id, company.name, count(persons.id) as count
FROM persons
LEFT JOIN company ON persons.company_id = company.id
GROUP BY company.name
ORDER BY company.name ASC, persons.id ASC;
-- The results will be:
-- |ID | NAME | COUNT|
-- |1 | Google | 2 |
-- |3 | Microsoft| 3 |
-- EXAMPLE 2 - Cascade order
-- base query
SELECT persons.*, company.* FROM persons
LEFT JOIN company ON persons.company_id = company.id
ORDER BY company.type ASC, persons.status ASC;
-- grouping query
SELECT MAX(persons.id) as id, company.type, count(persons.id) as count
FROM persons
LEFT JOIN company ON persons.company_id = company.id
GROUP BY company.type
ORDER BY company.type ASC, persons.status ASC;
-- The results will be:
-- |ID | NAME| COUNT|
-- |3 | 1 | 2 |
-- |2 | 2 | 3 |
Just change MAX() to MIN() to get the first row instead of the last row in each group.
To get the extreme values of cascading columns, see SQL : Using GROUP BY and MAX on multiple columns. Use that in the subquery part of the query to get the row containing those extremes, as in SQL select only rows with max value on a column.
So the form of the full query is:
SELECT t1.id, t1.grouped_column, t2.count
FROM yourTable AS t
JOIN (SELECT t3.grouped_column, t3.order_column1, MIN(t4.order_column2) AS order_column2, SUM(t3.count) AS count
FROM (SELECT grouped_column, MIN(order_column1) AS order_column1, COUNT(*) AS count
FROM yourTable
GROUP BY grouped_column) AS t3
JOIN yourTable AS t4
ON t3.grouped_column = t4.grouped_column AND t3.order_column1 = t4.order_column1
GROUP BY t4.grouped_column, t4.order_column1) AS t2
ON t1.grouped_column = t2.grouped_column AND t1.ordered_column1 = t2.order_column1 AND t1.order_column2 = t2.order_column2
Since you want to operate on a join, I suggest you define a view that uses the join. Then you can use that view in place of yourTable in the above query.

Creating is_sold MySQL field based on index existence in another table

I have a simple set of products with serial numbers. If a product is sold, its serial number gets placed in sold_items while all items that ever existed remain in all_items.
Some sample data:
all_items
id | serial_number | product_name | product_price
1 | XXXXXXXXXXX01 | Laptop | 199
2 | XXXXXXXXXXX02 | Tablet | 99
sold_items
id | serial_number | sold_time
1 | XXXXXXXXXXX02 | [TIMESTAMP]
I'm trying to do something like this with my query:
SELECT
all_items.* ,
(JOIN sold_items ON sold_items.serial_number = all_items.serial_number) AS is_sold
FROM all_items
In this case, the expected output would be
[
0=>[
'id'=>1,
'serial_number'=>XXXXXXXXXXX01,
'product_name'=>Laptop,
'product_price'=>199,
'is_sold'=>0
],
1=>[
'id'=>1,
'serial_number'=>XXXXXXXXXXX02,
'product_name'=>Tablet,
'product_price'=>99,
'is_sold'=>1
]
]
Is this easily achievable with a single query?
Use a LEFT JOIN and test whether the ID in the other table is not null.
SELECT a.*, s.id IS NOT NULL AS is_sold
FROM all_items AS a
LEFT JOIN sold_items AS s ON a.serial_number = s.serial_number

MySQL Select/Join Multiple Row in User Meta Table

I have a table called user_meta and it contains data like:
---------------------------
| user_id | field | value |
---------------------------
| 1 | 1 | Green |
| 1 | 2 | Square |
| 1 | 3 | Big |
| 2 | 1 | Red |
| 2 | 2 | Square |
| 2 | 3 | Small |
----------------------------
The field column is the number of a form field in the user's profile. The value column is the value the user submitted via the form.
How do I write a MySQL query that returns all users who have 'green big squares'?
Thanks!
This will return the result that you want. This uses a WHERE clause to return all records that have the values that you want, then you count the distinct values to make sure there are only 3:
select user_id
from user_meta
where value in ('Green', 'Square', 'Big')
group by user_id
having count(distinct value) = 3
See SQL Fiddle with Demo
Using a subquery would work if you're stuck with that schema. It's not going to be very fast though.
select userid
from user_meta
where user_id in (
select user_id from user_meta
where (field = 1 and value = 'Green')
)
and user_id in (
select user_id from user_meta
where (field = 2 and value = 'Square')
)
and user_id in (
select user_id from user_meta
where (field = 3 and value = 'Big')
)
SELECT user_id
FROM user_meta user_meta1
JOIN user_meta user_meta2 ON user_meta1.UserID = user_meta2.UserID
JOIN user_meta user_meta3 ON user_meta2.UserID = user_meta3.UserID
WHERE user_meta1.value = 'Green' AND user_meta2.value='Square' AND user_meta3.value='big'

SQL: How to return an non-existing row?

Say I have the following table:
=================================================
| color_id | parent_id | language_id | name |
=================================================
| 1 | 50 | 1 | Black |
-------------------------------------------------
Then say I need the row WHERE parent_id = 50 AND language_id = 2. Obviously, I would get nothing back based on my example table. However, I still need a result -- probably something like this:
=================================================
| color_id | parent_id | language_id | name |
=================================================
| NULL | 50 | 2 | NULL |
-------------------------------------------------
Is there a way to do this in SQL?
You could do a union query of both the potentially valid record and your default, then select the first one:
SELECT * FROM
(SELECT color_id, parent_id, language_id, name, 1 as order_rank
FROM some_table
WHERE parent_id = %parent_id% AND language_id = %language_id%
UNION
SELECT NULL, %parent_id%, %language_id%, NULL, 2 as order_rank
)
ORDER BY order_rank
LIMIT 1
(Edited with static value for ordering as suggested by OMG Ponies)
try working with LEFT JOIN statement. i'm probably not doing this 100% but a bit of trial and error on your part should make this work.
SELECT table1.field1, table1.field2, table2.field3, table2.field4
FROM my_table table1
LEFT JOIN my_table table2 ON table1.field1=table2.field1 OR table1.field2=table2.field2
a left join on a forced fixed value first table SHOULD work.
select
YourTable.color_id,
ForcedSQL1Record.parent_id,
ForcedSQL1Record.language_id,
YourTable.name
from
( select 50 as Parent_ID,
2 as Language_ID
from YourTable
limit 1 ) ForcedSQL1Record
left join
YourTable
on ForcedSQL1Record.Parent_ID = YourTable.Parent_ID
AND ForcedSQL1Record Language_ID = YourTable.Language_ID