Mysql: Swap data for different rows - mysql

Suppose a table fruits that looks like this:
------------------------------------------
| id | name | color | calories |
------------------------------------------
| 1 | apple | red | 20 |
| 2 | orange | orange | 10 |
| 3 | grapes | green | 5 |
| 4 | bananas | yellow | 15 |
| 5 | plum | purple | 25 |
------------------------------------------
How can I swap the values of a row, with another, leaving the id number intact?
Example:
SWAP ROW WITH ID "5" WITH ROW WITH ID "2"
Result:
------------------------------------------
| id | name | color | calories |
------------------------------------------
| 1 | apple | red | 20 |
| 2 | plum | purple | 25 |
| 3 | grapes | green | 5 |
| 4 | bananas | yellow | 15 |
| 5 | orange | orange | 10 |
------------------------------------------
Note that all the values are intact except for the id.
I need to do this with a really large list of values, so I need a one-liner, or at most, something that doesn't require the creation of temporary tables, and things like that.
Note: id is unique
Thank you

You could use a join inequality to line up the rows you want to swap:
update fruit a
inner join fruit b on a.id <> b.id
set a.color = b.color,
a.name = b.name,
a.calories = b.calories
where a.id in (2,5) and b.id in (2,5)
http://sqlfiddle.com/#!18/27318a/5

Since ID is unique, it is difficult to just swap the IDs, it's easier to swap the column contents. A query like this might be what you need:
UPDATE
yourtable t1 INNER JOIN yourtable t2
ON (t1.id, t2.id) IN ((1,5),(5,1))
SET
t1.color = t2.color,
t1.name = t2.name,
t1.calories = t2.calories
Please see fiddle here.

Here's a way to store values temporarily without using a temp table or a dummy row in your fruit table:
SELECT name, color, calories FROM fruit WHERE id = 2 INTO #name, #color, #calories;
UPDATE fruit AS f1, fruit AS f2
SET
f1.name = f2.name, f2.name = #name,
f1.color = f2.color, f2.color = #color,
f1.calories = f2.calories, f2.calories = #calories
WHERE (f1.id, f2.id) = (2, 5);
Here's another solution that uses a dummy id value:
UPDATE fruit SET id = 0 WHERE id = 5;
UPDATE fruit SET id = 5 WHERE id = 2;
UPDATE fruit SET id = 2 WHERE id = 0;

If your operations are based on ID, and you want to swap entire rows, a fancy way of swapping UNIQUE IDs is to start numbering them at 1, and use 0 as a temporary value.
Another way of performing this is using an unsigned column, and using a designated value (ie.: -1) for temporary. I wouldn't really recommend the latter, as we are effectively wasting space with this method. See http://dev.mysql.com/doc/refman/5.0/en/numeric-type-overview.html for more details.

Related

MySQL How to SELECT where field equals something in another table?

Take two example tables:
TableOne
+----+----------+-------------+------------+------------+--+
| id | uid | thingone | thingtwo | thingthree | |
+----+----------+-------------+------------+------------+--+
| 1 | 7 | 0 | 1 | 1 | |
| 2 | 8 | 1 | 1 | 0 | |
+----+----------+-------------+------------+------------+--+
and
TableTwo
+----+----------+-------------+------------+------------+--+
| id | oid | thingone | thingtwo | thingthree | |
+----+----------+-------------+------------+------------+--+
| 1 | 7 | Apple | Coconut | Grape | |
| 2 | 8 | Potato | Orange | Banana | |
+----+----------+-------------+------------+------------+--+
So in this example userid 7 would get Coconut and Grape, but not Apple. Userid 8 would get Potato and Orange, but not banana. I am wanting to do this the most efficient way and I realize I could do two separate queries with some php processing, but I want to do it with a single query if feasible.
What I need to do is (in a single query) get the row from TableOne by id and then select the row from TableTwo where theoid = the id of TableOne but only get the corresponding row from TableTwo if it is 1 and not 0 in TableOne.
Can any one help please?
You can achieve it by using IF and comparing the columns from both tables 1 by 1. To compare the tabletwo from tableone you need to use JOIN, in this query I use a LEFT JOIN.
SELECT a.id, a.`uid`,
IF(a.`thingone`=1, b.`thingone`, NULL) AS thingone,
IF(a.`thingtwo`=1, b.`thingtwo`, NULL) AS thingtwo,
IF(a.`thingthree`=1, b.`thingthree`, NULL) AS thingthree FROM tableone a
LEFT JOIN tabletwo b ON uid=oid;
Check MySQL IF() Function for more details.
you need to make relational tables and then use join query
What about this:
select case when t1.thingone = 1 then t2.thingone else '' end,
case when t1.thingtwo = 1 then t2.thingtwo else '' end,
case when t1.thingthree = 1 then t2.thingthree else '' end
from TableOne t1 join TableTwo t2 on t1.uid=t2.oid
You might need to concatenate these three or convert them into three rows, depending how how the three things should be represented.

How can I select data from table1 with multiple attributes from table2 in mysql?

I have two tables in mysql. The first one has user data for example, the second one has attributes data.
I want to select each user from table one and get all attributes for him from table two.
e.g.
table 1:
| userid | name |
| 1 | John |
| 2 | Billie |
table 2:
| userid | attribute |
| 1 | male |
| 1 | taxi driver |
| 1 | 45 years |
| 2 | female |
| 2 | clerk |
So I want to get my mysql results like this:
| userid | name | attributes |
| 1 | John | male, taxi driver, 45 years |
| 2 | Billie | female, clerk |
I absolutely have noch idea, how to get these attributes consolidated (maybe even comma seperated). I also searched here, but found nothing similar.
Can you help please? Thanks
I think you can user GROUP_CONCAT for that perhaps.
SELECT userid, name, GROUP_CONCAT(attribute) as attributes
FROM table1
INNER JOIN table2 ON table1.userid = table2.userid
GROUP BY table2.userid
See this SQLFiddle example: http://sqlfiddle.com/#!9/fd365d4/6/0
;with SampleDataR as
(
select *, ROW_NUMBER() over (partition by title, subtitle order by value) rownum
from test12
)
select distinct title, subtitle,(
select value
+ case when s1.rownum = (select MAX(rownum) from SampleDataR where title = s1.title and subtitle = s1.subtitle)
then '' else ',' end from SampleDataR s1
where s1.title = s2.title and s1.subtitle = s2.subtitle
for xml path(''),type).value('(.)[1]','varchar(max)') csvList
from SampleDataR s2

MySQL: Joining two tables, but getting just the first value in second table

I have two tables that I am trying to join.
car_make Table:
id | name | color
---------------------------
12 | Tayota | red
13 | Ford | gray
15 | Tesla | red
17 | GM | blue
car_type table:
id | car_id | image_one | image_two | image_three
--------------------------------------------------------------------------
1 | 12 | tayota1.jpg | tayota2.jpg | tayota3.jpg
2 | 17 | gm1.jpg | gm2.jpg | gm3.jpg
3 | 12 | tayota3.jpg | tayota4.jpg | tayota5.jpg
4 | 13 | ford1.png | ford2.png | ford3.png
5 | 13 | ford4.png | ford5.png | ford6.png
I want to grab and display every row within car_make, and join the first image_one instance for each make.
For example, I would like it to output:
Row 1: Tayota, red, tayota1.jpg
Row 2: Ford, gray, ford1.jpg
Row 3: Tesla, red, NULL
Row 4: GM, blue, gm1.jpg
How would I structure this query?
Because you want the equivalent of a left join and only want one row, the easiest way might be a correlated subquery:
select cm.*,
(select ct.image_one
from car_type ct
where ct.car_id = cm.id
order by ct.id
limit 1
) as image_one
from car_make cm;
There are several ways you can do this. Here's one using a sub-query to ensure you're only selecting the 1st car type per car make
select * from car_make cm
left join car_type ct on ct.car_id = cm.id
and ct.id = (select min(id) from car_type ct2 where ct2.car_id = ct.car_id)

select records from Foreign Key table where one item matches multiple condition

I have two tables like below. how can I select records that have values 'orange' and 'blue' in a same time.
+----+----------+
| ID |SECOND_ID |
+----+----------+
| 10 | 1 |
| 20 | 2 |
| 30 | 3 |
+----+----------+
+-----------+----------+
| SECOND_ID | COLOR |
+-----------+----------+
| 1 | blue |
| 1 | orange |
| 2 | blue |
| 2 | orange |
| 3 | orange |
+-----------+----------+
EDIT
ok I admit that I didn't explain the problem well. first let's call the tables items for first table and items_color for second as Alex did.
these tables have one-to-many relationship where the SECOND_ID have more than one value each time. Now I want select rows that have blue and orange in a same time and It should be the row with ID = 1 and 2.
thanks for your time.
http://sqlfiddle.com/#!9/05254/1
SELECT *,
SUM(IF(items_colors.color='blue',1,0)) as blue,
SUM(IF(items_colors.color='orange',1,0)) as orange
FROM items
LEFT JOIN items_colors
ON items.second_id = items_colors.second_id
GROUP BY items.id
HAVING blue>0 and orange>0
There's many ways, simpliest one will be with subqueries:
SELECT'second_id' FROM 'table' WHERE 'color' = 'blue' AND 'second_id' =
(SELECT 'second_id' FROM 'table' WHERE 'color' = 'orange')
But I think this is not the most optimized way
Also, you can try with an INNER JOIN (it will work like an intersection)
SELECT * FROM items_colors as A INNER JOIN items_colors AS B ON
A.SECOND_ID = B.SECOND_ID AND A.color = 'blue' AND B.color = 'orange'

Mysql, inner join in multiple columns with the same name

So, I have two tables, one of which is like this:
Table: data
id | col_1 | col_2 | col_3 | col_4
------------------------------------------------------
1 | 167 | 12 | 15 | something1
2 | 198 | 27 | 12 | something2
3 | 253 | 15 | 17 | something3
and Table: catalog
id | col_1
-----------------
12 | red
15 | yellow
17 | pink
27 | green
Now, what I am trying to do is get col_1, col_2, col_3 and col_4 from the data table, but instead of getting the values of col_2 and col_3, these should be replaced by the col_1 of the catalog table, according to the catalog id.
For example, I want it to return, for every row of the data table, the following info:
167 | red | yellow | something1
198 | green | red | something2
253 | yellow | pink | something3
I tried this:
SELECT data.col_1, catalog.col_1, catalog.col_1, data.col_4
FROM data
INNER JOIN catalog ON data.col_2 = catalog.id
INNER JOIN catalog ON data.col_3 = catalog.id
but to no effect and surprise.
I simply can't find how to inner join multiple columns of one table to a single column of another, and Google has not been of great help. I actually don't know if I am searching with the right keywords.
You have to give the tablenames an alias, because it doesn't know where catalog refers to.
SELECT data.col_1, c1.col_1, c2.col_1, data.col_4
FROM data
INNER JOIN catalog c1 ON data.col_2 = c1.id
INNER JOIN catalog c2 ON data.col_3 = c2.id