example table:
+--------+--------+-------+------+
| source | target | count | prob |
+--------+--------+-------+------+
| cat | dog | 1 | 0 |
| dog | cat | 1 | 0 |
+--------+--------+-------+------+
I need to let prob = count/ total of count
and I using
update test set prob = count / (select sum(count) from EM);
and it failed ,how I suppose to do ?
MySQL doesn't like referring to the table being updated, in a subquery. To get around it, wrap it in another select to force it to form a temporary table.
update test
set prob = count / (select * from (select sum(count) from test) q )
Related
I don't know how to explain this in words. So please let me say an example.
Suppose the items table sorted by order column:
| id | name | order |
| 5 | x | 1 |
| 2 | y | 3 |
| 3 | z | 4 |
| 7 | p | 8 |
I want to update order column in a way which each of them has 1 difference with their successive row with keeping the order.
Desired result:
| id | name | order |
| 5 | x | 1 |
| 2 | y | 2 |
| 3 | z | 3 |
| 7 | p | 4 |
Edit:
Selecting row_number() isn't my solution as I want to change orders and I'm not just looking for the row number.
In MySQL8, just use row_number():
select t.*,
row_number() over(order by ord) as new_ord
from mytable t
This demonstrates that the information can easily be computed on the fly when needed and leads to the finding that storing such derived information might not be a good idea. It is tedious to keep it up to date when new rows are added or deleted.
Instead, you can use the above query, or put it in a view:
create view myview as
select t.*,
row_number() over(order by ord) as new_ord
from mytable t
Note: order is a language keyword, I used ord instead.
If you really need an update, for a one-time task for example:
update mytable t
inner join (
select id, row_number() over(order by ord) as new_ord from mytable
) t1 on t1.id = t.id
set t.ord = t1.new_ord
I would suggest using view for such requirement as also mentioned in other answer.
If this is the one time activity and if order is unique for each record then you can use the following query which uses corelated sub-query.
Update your_table t
Set t.order = (select count(1)
From your_table tt where tt.order <= t.order);
I have a table containing some similar rows representing objects for a game. I use this table as a way to select objects randomly. Of course, I ignore the size of the table. My problem is that I would like to have a single query that returns the probability to select every object and I don't know how to proceed.
I can get the total number of objects I have in my table:
select count(id) from objects_desert_tb;
Which returns
+-----------+
| count(id) |
+-----------+
| 81 |
+-----------+
1 row in set (0.00 sec)
and I have a query that return the number of occurence of every object in the table:
select name, (count(name)) from objects_desert_tb group by name;
which gives:
+-------------------+---------------+
| name | (count(name)) |
+-------------------+---------------+
| carrots | 5 |
| metal_scraps | 14 |
| plastic_tarpaulin | 8 |
| rocks_and_stones | 30 |
| wood_scraps | 24 |
+-------------------+---------------+
5 rows in set (0.00 sec)
Computing the probability for every object just consist in doing (count(name)) divided by the total number of rows in the table. For example with the row carrots, just compute 5/81, from the two queries given above. I would like a single query that would return:
+-------------------+---------------+
| carrots | 5/81 = 0.06172839
| metal_scraps | 0.1728...
| plastic_tarpaulin | 0.09876...
| rocks_and_stones | 0.37...
| wood_scraps | 0.29...
+-------------------+---------------+
Is there a way to use the size of the table as a variable inside a SQL query? Maybe by nesting several queries?
Cross join your queries:
select c.name, c.counter / t.total probability
from (
select name, count(name) counter
from objects_desert_tb
group by name
) c cross join (
select count(id) total
from objects_desert_tb
) t
In MySQL 8+, you would just use window functions:
select name, count(*) as cnt,
count(*) / sum(count(*)) over () as ratio
from objects_desert_tb
group by name;
I hope i'm explaining this properly... but i'm trying to update a column in a table with 30k rows with a repeated sequence.
I've populated entire columns before with random numbers using:
UPDATE locations SET template = CAST((RAND() * 4)+1 AS UNSIGNED);
Which gave:
2
4
5
1
3
etc. in a random fashion throughout the 30k rows...
I would like to enter a query that can produce a repeated sequence like:
1
2
3
4
5
1
2
3
4
5
across all 30k rows.
I've been looking into loops and auto increments but can't get it to work.
Any help much appreciated :)
Perhaps using a variable will do for example
DROP TABLE IF EXISTS T;
CREATE TABLE T(ID INT, SEQNO INT);
INSERT INTO T VALUES (1,NULL),(2,NULL),(3,NULL),(4,NULL),(5,NULL),(6,NULL),(7,NULL);
UPDATE T
SET SEQNO = (SELECT IF(#RN = 2 ,#RN:=1,#RN:=#RN + 1) FROM (SELECT #RN:=0) R)
WHERE 1 = 1
+------+-------+
| ID | SEQNO |
+------+-------+
| 1 | 1 |
| 2 | 2 |
| 3 | 1 |
| 4 | 2 |
| 5 | 1 |
| 6 | 2 |
| 7 | 1 |
+------+-------+
Thanks for the suggestions... I had a hard time finding an answer but eventually found something that would do exactly what I was after. I must admit it is far beyond my capabilities, but here it is:
SET #row_number = 0;
SET #max_num = 75;
update locations loc1
join (
select
if ((num % #max_num) = 0, #max_num, (num % #max_num)) as num2,
a.*
from (
select
(#row_number:=#row_number + 1) AS num,
loc.*
from locations loc
ORDER BY num
) a
order by num, num2
) loc2 on (loc2.id = loc1.id)
set loc1.colname = loc2.num2;
I have a temporary table I've derived from a much larger table.
+-----+----------+---------+
| id | phone | attempt |
+-----+----------+---------+
| 1 | 12345678 | 15 |
| 2 | 87654321 | 0 |
| 4 | 12345678 | 16 |
| 5 | 12345678 | 14 |
| 10 | 87654321 | 1 |
| 11 | 87654321 | 2 |
+-----+----------+---------+
I need to find the id (unique) corresponding to the highest attempt made on each phone number. Phone and attempt are not unique.
SELECT id, MAX(attempt) FROM temp2 GROUP BY phone
The above query does not return the id for the corresponding max attempt.
Try this:
select
t.*
from temp2 t
inner join (
select phone, max(attempt) attempt
from temp2
group by phone
) t2 on t.phone = t2.phone
and t.attempt = t2.attempt;
It will return rows with max attempts for a given number.
Note that this will return multiple ids if there are multiple rows for a phone if the attempts are same as maximum attempts for that phone.
Demo here
As an alternative to the answer given by #GurV, you could also solve this using a correlated subquery:
SELECT t1.*
FROM temp2 t1
WHERE t1.attempt = (SELECT MAX(t2.attempt) FROM temp2 t2 WHERE t2.phone = t1.phone)
This has the advantage of being a bit less verbose. But I would probably go with the join option because it will scale better for large data sets.
Demo
I have a table like this:
startyearmonthday| id
20130901 | 1
20131004 | 2
20130920 | 3
20131105 | 4
20131009 | 5
I want to write a query where I can return a table like this:
startyearmonthday| id | endyearmonthday
20130901 | 1 | 20130920
20130920 | 3 | 20131004
20131004 | 2 | 20131009
20131009 | 5 | 20131105
20131105 | 4 | null
So I want the end date based on the next earliest start date after the current start date. I imagine some sort of join is involved but I can't figure it out...
I would be inclined to do this with a correlated subquery:
select t.*,
(select startyearmonthday
from t t2
where t2.startyearmonthday > t.startyearmonthday
order by t2.startyearmonthday
limit 1
) as endyearmonthday
from t;
As with your earlier question, this will run pretty quickly with an index on t(startyearmonthday).
Try this (assuming there are no repeated rows):
select a.*, b.startyearmonthday as endyearmonthday
from table_name a
left join table_name b
on b.startyearmonthday > a.startyearmonthday and not exists(select startyearmonthday from table_name c where a.startyearmonthday < c.startyearmonthday and c.startyearmonthday < b.startyearmonthday)