Following is my table structure:
+------+----------+
| product | seq |
+------+----------+
| a | 1 |
| b | 1 |
| a | 2 |
| a | 3 |
| b | 2 |
+------+----------+
If my inputs are a and 2 then, i need to change the sequence number and the the output will be
+------+----------+
| product | seq |
+------+----------+
| a | 2 |
| b | 1 |
| a | 1 |
| a | 3 |
| b | 2 |
+------+----------+
am using the logic as :
update mytable SET seq=if(seq=2,1,2), seq=if(seq=1,2,1) where product='a'
But it will not make any changes in the table
Try Like this
UPDATE table1 s1 , table1 s2 SET s1.seq=s2.seq,
s2.seq=s1.seq WHERE s1.seq=2 and s2.seq=1 and
s1.product='a' and s2.product='a';
Related
There are two tables,
Table A has a three-level structure that looks like
| id | name | level | up_level_id |
| :------- | :-------: | :------: | ----------:|
| 1 | lv1_name1 | 1 | null |
| 2 | lv1_name2 | 1 | null |
| 3 | lv2_name1 | 2 | 1 |
| 4 | lv2_name2 | 2 | 2 |
| 5 | lv3_name1 | 3 | 3 |
| 6 | lv3_name2 | 3 | 3 |
| 7 | lv3_name3 | 3 | 4 |
| 8 | lv3_name4 | 3 | 4 |
Table B looks like
| amount | org_id |
| -------- | -------- |
| 12,000 | 5 |
| 15,000 | 6 |
| 20,000 | 7 |
| 18,000 | 8 |
Table A and Table B can be joined on A.id=B.org_id, but they are all at the level-3 of Table A(Only level-3 has their amount)
I want to query the top-level name,level-1 name, and the summary amount that looks like
| sum_amount | top_lvl_name |
| -------- | -------- |
| 27,000 | lv1_name1 |
| 38,000 | lv1_name2 |
For Testing, I have already accomplished the query of the level-1 name from the level-3 id in TableA
The SQL is as follows
SELECT name
FROM TableA
WHERE id IN (
SELECT up_level_id
FROM Table A
WHERE id IN (
SELECT up_level_id
FROM Table A
WHERE id=5) --query the id:5's top-level name
);
But when I join these two tables as follows, it goes wrong
SELECT sum(amount) AS sum_amount, name AS top_lvl_name
FROM TableA, TableB
WHERE id = org_id
AND id IN (
SELECT up_level_id
FROM TableA
WHERE id IN (
SELECT up_level_id
FROM TableA
WHERE TableA.id IN(
SELECT org_id
FROM TABLEB
)
)
);
I get nothing as above
What can I do to make this query to be correct?
Thanks for everyone's answer and comment.
Finally, I find it very difficult to query the result as I wish. So, I've come up with a shortcut——create a new table that a three-level structure recorded horizontally, which looks like
| lv1_id | lv2_name | lv2_id | lv2_name | lv3_id | lv3_name |
| :------- | :-------: | :------: | :----------:| :------: | :----------:|
| 1 | lv1_name1 | 3 | lv2_name1 | 5 | lv3_name1 |
| 1 | lv1_name1 | 3 | lv2_name1 | 6 | lv3_name2 |
| 2 | lv1_name2 | 4 | lv2_name1 | 7 | lv3_name3 |
| 2 | lv1_name2 | 4 | lv2_name1 | 8 | lv3_name4 |
As above,I can easily connect two tables
Let's say, I have 2 tables
user
+----+--------+
| id | status |
+----+--------+
| 1 | A |
| 2 | A |
+----+--------+
article
+----+-----+--------+
| id | uid | status |
+----+-----+--------+
| 1 | 1 | A |
| 2 | 2 | A |
| 3 | 2 | A |
| 4 | 2 | A |
| 5 | 1 | A |
| 6 | 2 | A |
| 7 | 2 | A |
| 8 | 1 | A |
| 9 | 2 | A |
| 10 | 2 | A |
+----+-----+--------+
How can I add a foreign key that if I run this query:
UPDATE user SET status='B' WHERE id=1 OR id=2;
the result will be:
user
+----+--------+
| id | status |
+----+--------+
| 1 | B |
| 2 | B |
+----+--------+
article
+----+-----+--------+
| id | uid | status |
+----+-----+--------+
| 1 | 1 | B |
| 2 | 2 | B |
| 3 | 2 | B |
| 4 | 2 | B |
| 5 | 1 | B |
| 6 | 2 | B |
| 7 | 2 | B |
| 8 | 1 | B |
| 9 | 2 | B |
| 10 | 2 | B |
+----+-----+--------+
Or in other words, if I update column user.status, MySQL will automatically update column article.status with the respective value.
How can I create this foreign key?
That job is not foreign key could finish. Use an update trigger, but for better Database compatibility, do this action on you code is preferred.
Trigger code:
CREATE TRIGGER SetArticleStatus AFTER UPDATE ON user
FOR EACH ROW
BEGIN
UPDATE `article`
SET status = NEW.status
WHERE uid = NEW.id
END
Since your FOREIGN KEY is only uid and doesn't know about status the thing you want can't be accomplished using only foreign-keys. This looks like a good use-case for a on-update-trigger.
Assume following table:
+----+-----------+
| id | session |
+----+-----------+
| 1 | abcd1234 |
| 2 | abcd1234 |
| 3 | abcd1234 |
| 4 | qwert5678 |
| 5 | qwert5678 |
| 6 | abcd1234 |
| 7 | abcd1234 |
| 8 | qwert5678 |
| 9 | abcd1234 |
| 10 | qwert5678 |
| 11 | qwert5678 |
| 12 | qwert5678 |
+----+-----------+
Suppose we want to get the first id of a given session, then set every instance of that session to the id for all sessions, such that the table becomes:
+----+-----------+
| id | session |
+----+-----------+
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 4 | 4 |
| 5 | 4 |
| 6 | 1 |
| 7 | 1 |
| 8 | 4 |
| 9 | 1 |
| 10 | 4 |
| 11 | 4 |
| 12 | 4 |
+----+-----------+
We have a table with approximately 45M records, and are essentially changing every instance of column b to the value of min(column a) when grouped by column b.
Is there a way to do this in a single query? We have attempted several.
update example e
set session =
(select id from
(select id,min(session)
from example as first_id
group by session
) as this_id
);
...which errors out: "Subquery returns more than 1 row".
update example e
join
(select id
from
(select id,min(session)
from example as first_id
group by session
) as this_id
) as etable
set session = first_id;
...which errors out: "Unknown column 'first_id' in 'field list'". Also used 'this_id' to the same effect.
And other queries. Is this possible in a single query? Are we thinking about this incorrectly?
Query:
SQLFIDDLEExample
UPDATE example
SET session =(SELECT MIN(e2.ID)
FROM (SELECT *
FROM example) e2
WHERE e2.session = example.session)
Result:
| ID | SESSION |
----------------
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 4 | 4 |
| 5 | 4 |
| 6 | 1 |
| 7 | 1 |
| 8 | 4 |
| 9 | 1 |
| 10 | 4 |
| 11 | 4 |
| 12 | 4 |
mysql> select * from product;
+------------+---------------+
| product_id | name |
+------------+---------------+
| 1 | Car |
| 2 | House |
| 3 | Cat |
| 4 | Blank Product |
+------------+---------------+
4 rows in set (0.00 sec)
mysql> select * from tag;
+--------+-----------+
| tag_id | name |
+--------+-----------+
| 1 | Expensive |
| 2 | Fast |
| 3 | Mean |
| 4 | Large |
| 5 | Small |
| 6 | Alive |
| 7 | Blank Tag |
+--------+-----------+
7 rows in set (0.00 sec)
mysql> select * from product_tag;
+------------+--------+
| product_id | tag_id |
+------------+--------+
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
| 1 | 4 |
| 2 | 1 |
| 2 | 4 |
| 3 | 2 |
| 3 | 3 |
| 3 | 5 |
| 3 | 6 |
+------------+--------+
10 rows in set (0.00 sec)
Why does the following query return my blank tag but not my blank product?
mysql> select * from product_tag right join product using (product_id)
right join tag using (tag_id);
+--------+-----------+------------+-------+
| tag_id | name | product_id | name |
+--------+-----------+------------+-------+
| 1 | Expensive | 1 | Car |
| 1 | Expensive | 2 | House |
| 2 | Fast | 1 | Car |
| 2 | Fast | 3 | Cat |
| 3 | Mean | 1 | Car |
| 3 | Mean | 3 | Cat |
| 4 | Large | 1 | Car |
| 4 | Large | 2 | House |
| 5 | Small | 3 | Cat |
| 6 | Alive | 3 | Cat |
| 7 | Blank Tag | NULL | NULL |
+--------+-----------+------------+-------+
11 rows in set (0.00 sec)
You are using right join. In your query tags ids are the base where MySQL will start matching. The right join is evaluated from right to left. If you break your query into two parts. The first one will be:
select * from product_tag right join tag using (tag_id);
+--------+-----------+------------+
| tag_id | name | product_id |
+--------+-----------+------------+
| 1 | expensive | 1 |
| 1 | expensive | 2 |
| 2 | fast | 1 |
| 2 | fast | 3 |
| 3 | mean | 1 |
| 3 | mean | 3 |
| 4 | larg | 1 |
| 4 | larg | 2 |
| 5 | small | 3 |
| 6 | alive | 3 |
| 7 | blank tag | NULL |
+--------+-----------+------------+
As you see there is not product_id that matches with the blank tag. The explains why joining this result with the product table will give you the result you saw.
If you use left join instead you'll get this result:
select * from product_tag left join product using (product_id) left join tag using (tag_id);
+--------+------------+-------+-----------+
| tag_id | product_id | name | name |
+--------+------------+-------+-----------+
| 1 | 1 | car | expensive |
| 2 | 1 | car | fast |
| 3 | 1 | car | mean |
| 4 | 1 | car | larg |
| 1 | 2 | house | expensive |
| 4 | 2 | house | larg |
| 2 | 3 | cat | fast |
| 3 | 3 | cat | mean |
| 5 | 3 | cat | small |
| 6 | 3 | cat | alive |
+--------+------------+-------+-----------+
There is no row associating product id 4 with a tag. You need to add a row to the product_tag table like the following:
+------------+--------+
| product_id | tag_id |
+------------+--------+
| 4 | 7 |
+------------+--------+
You are using a RIGHT JOIN so all the rows in the right table i.e "tag" will be returned even if there is no match in the joined tables.
Is there a way in SQL (MySQL) to do a "round robin" ORDER BY on a particular field?
As an example, I would like to take a table such as this one:
+-------+------+
| group | name |
+-------+------+
| 1 | A |
| 1 | B |
| 1 | C |
| 2 | D |
| 2 | E |
| 2 | F |
| 3 | G |
| 3 | H |
| 3 | I |
+-------+------+
And run a query that produces results in this order:
+-------+------+
| group | name |
+-------+------+
| 1 | A |
| 2 | D |
| 3 | G |
| 1 | B |
| 2 | E |
| 3 | H |
| 1 | C |
| 2 | F |
| 3 | I |
+-------+------+
Note that the table may have many rows, so I can't do the ordering in the application. (I'd obviously have a LIMIT clause as well in the query).
I'd try something like:
SET #counter = 0;
SELECT (#counter:=#counter+1)%3 as rr, grp, name FROM table ORDER by rr, grp
What you can do is create a temporary column in which you create sets to give you something like this:
+-------+------+-----+
| group | name | tmp |
+-------+------+-----+
| 1 | A | 1 |
| 1 | B | 2 |
| 1 | C | 3 |
| 2 | D | 1 |
| 2 | E | 2 |
| 2 | F | 3 |
| 3 | G | 1 |
| 3 | H | 2 |
| 3 | I | 3 |
+-------+------+-----+
To learn how to create the sets, have a look at this question/answer.
Then its a simple
ORDER BY tmp, group, name
You can use MySQL variables to do this.
SELECT grp, name, #row:=#row+1 from table, (SELECT #row:=0) r ORDER BY (#row % 3);
+------+------+--------------+
| grp | name | #row:=#row+1 |
+------+------+--------------+
| 1 | A | 1 |
| 2 | D | 4 |
| 3 | G | 7 |
| 1 | B | 2 |
| 2 | E | 5 |
| 3 | H | 8 |
| 1 | C | 3 |
| 2 | F | 6 |
| 3 | I | 9 |
+------+------+--------------+