I need some help in mysql statement
Ive table1 with 7 column and table 2 with 8 column the extra column named ranking , my statement should be like
select all from table 1 then sort it by " number of users " insert it in table 2 and ranking start 1 2 3 etc,
table 1 :
username | email | number of users
jack a#a.com 75
ralf b#b.com 200
anne c#c.com 12
sonny d#d.com 300
===================================
here where i need to INSERT and RANKING based on number of users
table 2
ranking | username | email | number of users
1
2
3
I would avoid to use another table. A single query suffices.
create table mytable (
id int not null auto_increment primary key,
username varchar(50),
email varchar(50),
number int
) engine = myisam;
insert into mytable (username,email,number)
values
('a','aaa',10),
('b','bbb',30),
('c','ccc',50),
('d','ddd',30),
('e','eee',20),
('f','fff',45),
('g','ggg',20);
select #r:=#r+1 as rnk,username,email,number
from mytable,(select #r:=0) as r order by number desc
+------+----------+-------+--------+
| rnk | username | email | number |
+------+----------+-------+--------+
| 1 | c | ccc | 50 |
| 2 | f | fff | 45 |
| 3 | b | bbb | 30 |
| 4 | d | ddd | 30 |
| 5 | e | eee | 20 |
| 6 | g | ggg | 20 |
| 7 | a | aaa | 10 |
+------+----------+-------+--------+
7 rows in set (0.00 sec)
This is a smarter version that considers ties
select #r:=#r + 1 as rn, username,email,
#pos:= if(#previous<>number,#r,#pos) as position,
#previous:=number as num
from mytable,(select #r:=0,#pos:=0,#previuos:=0) as t order by number desc
+------+----------+-------+----------+--------+
| rn | username | email | position | num |
+------+----------+-------+----------+--------+
| 1 | c | ccc | 1 | 50 |
| 2 | f | fff | 2 | 45 |
| 3 | b | bbb | 3 | 30 |
| 4 | d | ddd | 3 | 30 |
| 5 | e | eee | 5 | 20 |
| 6 | g | ggg | 5 | 20 |
| 7 | a | aaa | 7 | 10 |
+------+----------+-------+----------+--------+
7 rows in set (0.00 sec)
INSERT INTO table2
SELECT #rank := #rank + 1, table1.* FROM table1
JOIN( SELECT #rank := 0 ) AS init
ORDER BY number_of_users DESC
You need to do something like this:
SELECT * FROM `table1`
INNER JOIN `table2` USING ([a common filed name here])
ORDER BY table2.[the filed name here]
Good Luck!
Related
Is there a way how can I query the previous row value and merge to current row, here is my sample table scenario:
+-------------------------------------+
| ColA | ColB | ColValue | Date |
|------|------|----------|------------|
| AAA | 111 | 5 | 2017-04-23 |
| AAA | 111 | 4 | 2017-04-22 |
| AAA | 111 | 3 | 2017-04-21 |
| BBB | 222 | 5 | 2017-04-30 |
| BBB | 222 | 4 | 2017-04-29 |
+-------------------------------------+
And my expected result should be this, just want to get the previous and current value and group it by selected columns and date.
+--------------------------------------------------+
| ColA | ColB | PreValue | CurValue | Date |
|------|------|----------|-------------------------|
| AAA | 111 | 4 | 5 | 2017-04-23 |
| AAA | 111 | 3 | 4 | 2017-04-22 |
| AAA | 111 | N/A | 3 | 2017-04-21 |
| BBB | 222 | 4 | 5 | 2017-04-30 |
| BBB | 222 | N/A | 4 | 2017-04-29 |
+--------------------------------------------------+
any suggestions or solution, thanks in advance
Here is my actual query from my actual data as reference:
SELECT ai.APName, tbap.Value , tbap.DateTime, tbap.Comment, tbap.ModifiedBy, tbap.ToolName, d.Name as Strategy FROM (SELECT dt.*,ins.Value as ToolName FROM (SELECT av.*,ai.DocumentID,ai.IndexID FROM ControlAutomation.appartitionindexes ai
JOIN (SELECT * FROM ControlAutomation.appartitionvalues
where DateTime > '2017-04-22 23:17:13' and DateTime < '2017-04-26 23:18:28') av
ON ai.APPartitionID = av.APPartitionID) dt INNER JOIN factory.indexes ins ON ins.ID = dt.IndexID
where dt.comment like '%updateAdjustableParameter%'
group by dt.ID) tbap
INNER JOIN ControlAutomation.documents d ON d.ID = tbap.DocumentID
INNER JOIN appartitionindexes ai ON ai.APPartitionID = tbap.APPartitionID
GROUP BY tbap.ID
ORDER BY tbap.ToolName DESC, d.Name, tbap.DateTime DESC
LIMIT 100
Hope I correctly got your question: http://sqlfiddle.com/#!9/d815c/6
select
prev_query.cola as ColA,
prev_query.colb as ColB,
rhs.colvalue as PreValue,
prev_query.colvalue as CurValue,
prev_query.coldate as ColDate
from
prev_query left join prev_query as rhs
on prev_query.cola = rhs.cola
and prev_query.colb = rhs.colb
and prev_query.colvalue = rhs.colvalue + 1
order by
prev_query.cola, prev_query.colb, prev_query.coldate desc;
I want a query that selects all rows that have the UploadedbyUserID = Rand() (selects random id from possible UploadbyUserID in this case 4, 3 and 22 and only those 3 not 2 nor 5)
And if the rand gives 4 it outputs this:
+------+------+------------+--------------------+
| id | name | date | UploadedbyUserID |
+------+------+------------+--------------------+
| 1 | 2222 | Testing | 4 |
| 2 | Jack | description| 4 |
| 6 | Zara | 2007-02-06 | 4 |
+------+------+------------+--------------------+
This is the whole table
+------+------+------------+--------------------+
| id | name | date | UploadedbyUserID |
+------+------+------------+--------------------+
| 1 | 2222 | Testing | 4 |
| 2 | Jack | description| 4 |
| 3 | ffdsd| 2007-05-06 | 4 |
| 4 | dsm | 2007-05-27 | 3 |
| 5 | dddd | 2007-04-06 | 3 |
| 6 | Zara | 2007-02-06 | 4 |
| 7 | John | 2007-01-24 | 22 |
+------+------+------------+--------------------+
and if it randomizes 3 it outputs this
+------+------+------------+--------------------+
| id | name | date | UploadedbyUserID |
+------+------+------------+--------------------+
| 4 | dsm | 2007-05-27 | 3 |
| 5 | dddd | 2007-04-06 | 3 |
+------+------+------------+--------------------+
Ask if you need more information
Hmmm. This is one way:
select t.*
from (select uploadedbyuserid
from t
order by rand()
limit 1
) u join
t
using (uploadedbyuserid);
First, let me say that this is weighted by the number of times that a user has uploaded something. So, user "4" would appear a bit more often than "3", in your example. If this is an issue:
select t.*
from (select uploadedbyuserid
from (select distinct uploadedbyuserid from t) t
order by rand()
limit 1
) u join
t
using (uploadedbyuserid);
The next observation is that this can be compute intensive. If you have lots of rows, there are various ways to speed these up. For instance, one simple method would be to get about 1 out of 10000 rows:
select t.*
from (select uploadedbyuserid
from (select distinct uploadedbyuserid
from t
) t
where rand() < 0.001
order by rand()
limit 1
) u join
t
using (uploadedbyuserid);
I'm looking to allow for a custom ordering logic through mySQL that allows the following data set:
+----+-----------------+------------+-------+--+
| ID | item | Popularity | Views | |
+----+-----------------+------------+-------+--+
| 1 | A special place | 3 | 10 | |
| 2 | Another title | 5 | 12 | |
| 3 | Words go here | 1 | 15 | |
| 4 | A wonder | 2 | 8 | |
+----+-----------------+------------+-------+--+
To return an order that alternates, row by row, by popularity and then by views, so the return results look like:
+----+-----------------+------------+-------+--+
| ID | item | Popularity | Views | |
+----+-----------------+------------+-------+--+
| 3 | Words go here | 1 | 15 | |
| 2 | Another title | 5 | 12 | |
| 4 | A wonder | 2 | 8 | |
| 1 | A special place | 3 | 10 | |
+----+-----------------+------------+-------+--+
Where you will see the first row returns the 'most popular', the second row returns the most views, the third row returns the second most popular, and the 4th row returns the 2nd most views.
Currently I'm gathering an entire table through mySQL twice, and then merging these results in PHP. This isn't going to cut it when the database is large. Is this possible in mysql at all?
I guess something along these lines could work. Consider the following:
DROP TABLE IF EXISTS my_table;
CREATE TABLE my_table
(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
,x INT NOT NULL
,y INT NOT NULL
);
INSERT INTO my_table VALUES
(1,3,10),
(2,5,12),
(3,1,15),
(4,2, 8)
(5,4, 1);
We can rank x and y in turn, and then arrange those ranks in a single list - so will have x1,y1,x2,y2,etc - but all rows will appear twice; once for the x rank and once for the y rank...
SELECT * FROM
(
( SELECT a.*, COUNT(*) rank FROM my_table a JOIN my_table b ON b.x <= a.x GROUP BY a.id )
UNION ALL
( SELECT a.*, COUNT(*) rank FROM my_table a JOIN my_table b ON b.y <= a.y GROUP BY a.id )
) n
ORDER BY rank
+----+---+----+------+
| id | x | y | rank |
+----+---+----+------+
| 5 | 4 | 1 | 1 |
| 3 | 1 | 15 | 1 |
| 4 | 2 | 8 | 2 |
| 4 | 2 | 8 | 2 |
| 1 | 3 | 10 | 3 |
| 1 | 3 | 10 | 3 |
| 5 | 4 | 1 | 4 |
| 2 | 5 | 12 | 4 |
| 2 | 5 | 12 | 5 |
| 3 | 1 | 15 | 5 |
+----+---+----+------+
Now we can just grab the lowest rank for each id...
SELECT id
, x
, y
FROM
(
( SELECT a.*, COUNT(*) rank FROM my_table a JOIN my_table b ON b.x <= a.x GROUP BY a.id )
UNION ALL
( SELECT a.*, COUNT(*) rank FROM my_table a JOIN my_table b ON b.y <= a.y GROUP BY a.id )
) m
GROUP
BY id,x,y
ORDER
BY MIN(rank);
+----+---+----+
| id | x | y |
+----+---+----+
| 3 | 1 | 15 |
| 5 | 4 | 1 |
| 4 | 2 | 8 |
| 1 | 3 | 10 |
| 2 | 5 | 12 |
+----+---+----+
Incidentally, this should be faster with variables - but I cannot make that solution work at present - senior moment, perhaps.
Hello I would like to make event for my application that works by insert new 3 record for 1 userID every midnight so the quantity of rows must have
n x 3 n is userIDs
+---------+-----------+-------+------------+------+----------+-------------+-------+
| userID | userNAME | chaID | chaNAME | goal | gender | row_number | dummy |
+---------+-----------+-------+------------+------+----------+-------------+-------+
| 1 | Nanyang | 1 | blahblah | 1 | 2 | 1 | 1 |
| 1 | Nanyang | 21 | something | 1 | 2 | 2 | 1 |
| 1 | Nanyang | 2 | anything | 1 | 2 | 3 | 1 |
| 2 | Julie | 3 | x | 2 | 1 | 1 | 2 |
| 2 | Julie | 12 | y | 2 | 1 | 2 | 2 |
| 2 | Julie | 23 | z | 2 | 1 | 3 | 2 |
| 3 | Kingkong | 4 | a | 1 | 2 | 1 | 3 |
| 3 | Kingkong | 5 | b | 1 | 2 | 2 | 3 |
| 3 | Kingkong | 6 | c | 1 | 2 | 3 | 3 |
+---------+-----------+-------+------------+------+----------+-------------+-------+
the row_number will be looped until they're <= 3
from my written ..
set #num := 0, #type := ‘';
CREATE TABLE random
as
(
SELECT
*
FROM (
select userID,userNAME, chaID, chaNAME,goal,gender,
#num := if(#type = userID, #num +1,1) as row_number,
#type := userID as dummy
from userchar
order by userID
) as x where x.row_number <= 3)
Anyway I used to try to create table with Select the first/least/max row per group in SQL
and it works very well and get the result like i shown. then I need to insert into in event instead of create table so i got this code below.. because I can't use SET #parameterfor insert
INSERT INTO random(userID, userNAME, chaID, chaNAME, goal, gender,row_number,dummy,status)
select *
from (select userID, userNAME, chaID, chaNAME, goal, gender,
(#num := if(#type = userID, #num +1,1)
) as row_number,
userID as dummy,
#stat as status
from hb_usercha u cross join
(select #type = '', #num := 0, #stat := '') params
order by userID,rand()
)
where row_number <= 3;
and this is a result what I got
+---------+-----------+-------+------------+------+----------+-------------+-------+
| userID | userNAME | chaID | chaNAME | goal | gender | row_number | dummy |
+---------+-----------+-------+------------+------+----------+-------------+-------+
| 1 | Nanyang | 1 | blahblah | 1 | 2 | 1 | 1 |
| 1 | Nanyang | 21 | something | 1 | 2 | 1 | 1 |
| 1 | Nanyang | 2 | anything | 1 | 2 | 1 | 1 |
| 1 | Nanyang | 3 | s | 2 | 1 | 1 | 1 |
| 1 | Nanyang | 12 | o | 2 | 1 | 1 | 1 |
| 1 | Nanyang | 23 | m | 2 | 1 | 1 | 1 |
| 1 | Nanyang | 4 | e | 1 | 2 | 1 | 1 |
| 2 | Julie | 5 | xoxo | 1 | 2 | 1 | 2 |
| 2 | Julie | 6 | xxx | 1 | 2 | 1 | 2 |
+---------+-----------+-------+------------+------+----------+-------------+-------+
.
.
.
.
It seems row_number loop isn't working
And I have no idea what's happening
Both code are same just changed parameters path
So It would be very good if someone can explain to me
Thank you so much
Assuming you want to do it for all users exists in user_char table.
Using Union all to get 3 records of each user and store the result in temporary table.
DELIMITER $$
CREATE EVENT `event_run_midnight` ON SCHEDULE EVERY 24 HOUR STARTS '2016-02-09 00:00:00' ON COMPLETION NOT PRESERVE ENABLE DO
BEGIN
drop temporary table if exists temp_users_1;
create Temporary table temp_users_1
select users.*,#row_num:=#row_num+1 as row_num,userID as dummy
from(
select * from user_char
union all
select * from user_char
union all
select * from user_char
) as users,(select #row_num:=0) as row_number
order by UserID;
/*
Copy temp table data to other temp table as MySQL
not allows to use same temp table in single query.
*/
drop temporary table if exists temp_users_2;
create Temporary table temp_users_2
select * from temp_users_1;
-- final query which returns desired output :
INSERT INTO random(userID, userNAME, chaID, chaNAME, goal, gender,row_number,dummy)
Select usr.userID,
usr.userNAME,
usr.chaID,
usr.chaNAME,
usr.goal,
usr.gender,
usr.row_num-usr_grp.min_row_num+1 as row_number,
usr.userID as dummy
from temp_users_1 usr
inner join (
Select userID,
min(row_num) as min_row_num
from temp_users_2 group by userID
) usr_grp on usr.UserID=usr_grp.userID
where usr.row_num-usr_grp.min_row_num+1 <=3; -- Condition to show only 3 records of each users.
END$$
DELIMITER ;
Updates:
1- Added Event Creation.
2- Assuming you are inserting repetitive user records into table name random.
3- This Event will execute daily at 12:00 AM.
Note:
1- You may have to change the table names if tables names are different as in answer.
2- Make sure that you have enabled MySQL Event scheduler in Configuration file otherwise event will not run automatically.
Here is the link which help you enabling MySQL event scheduler if not enabled:
http://geeksterminal.com/enable-mysql-event-scheduler-status/1711/
I have table of orders. Each customer (identified by the email field) has his own orders. I need to give a different sequence of order numbers for each customer. Here is example:
----------------------------
| email | number |
----------------------------
| test#com.com | 1 |
----------------------------
| example#com.com | 1 |
----------------------------
| test#com.com | 2 |
----------------------------
| test#com.com | 3 |
----------------------------
| client#aaa.com | 1 |
----------------------------
| example#com.com | 2 |
----------------------------
Is possible to do that in a simple way with mysql?
If you want update data in this table after an insert, first of all you need a primary key, a simple auto-increment column does the job.
After that you can try to elaborate various script to fill the number column, but as you can see from other answer, they are not so "simple way".
I suggest to assign the order number in the insert statement, obtaining the order number with this "simpler" query.
select coalesce(max(`number`), 0)+1
from orders
where email='test1#test.com'
If you want do everything in a single insert (better for performance and to avoid concurrency problems)
insert into orders (email, `number`, other_field)
select email, coalesce(max(`number`), 0) + 1 as number, 'note...' as other_field
from orders where email = 'test1#test.com';
To be more confident about not assign at the same customer two orders with the same number, I strongly suggest to add an unique constraint to the columns (email,number)
create a column order_number
SELECT #i:=1000;
UPDATE yourTable SET order_number = #i:=#i+1;
This will keep incrementing the column value in order_number column and will start right after 1000, you can change the value or even you can even use the primary key as the order number since it is unique all the time
I think one more need column for this type of out put.
Example
+------+------+
| i | j |
+------+------+
| 1 | 11 |
| 1 | 12 |
| 1 | 13 |
| 2 | 21 |
| 2 | 22 |
| 2 | 23 |
| 3 | 31 |
| 3 | 32 |
| 3 | 33 |
| 4 | 14 |
+------+------+
You can get this result:
+------+------+------------+
| i | j | row_number |
+------+------+------------+
| 1 | 11 | 1 |
| 1 | 12 | 2 |
| 1 | 13 | 3 |
| 2 | 21 | 1 |
| 2 | 22 | 2 |
| 2 | 23 | 3 |
| 3 | 31 | 1 |
| 3 | 32 | 2 |
| 3 | 33 | 3 |
| 4 | 14 | 1 |
+------+------+------------+
By running this query, which doesn't need any variable defined:
SELECT a.i, a.j, count(*) as row_number FROM test a
JOIN test b ON a.i = b.i AND a.j >= b.j
GROUP BY a.i, a.j
Hope that helps!
You can add number using SELECT statement without adding any columns in table orders.
try this:
SELECT email,
(CASE email
WHEN #email
THEN #rownumber := #rownumber + 1
ELSE #rownumber := 1 AND #email:= email END) as number
FROM orders
JOIN (SELECT #rownumber:=0, #email:='') AS t