i want to sort my table in this manner.
This is the current state of my table:
And this would be the outcome:
So basically in pseudo code it's:
IF SAME STRING IN "tag" COLUMN THEN add both "power"
Can anyone suggest an efficient way to achieve this if any?
select id, sum(power), tag from YourTabeName group by tag
If you need to query from it I would just make it a view.
Create a new table called t1_temp with the exact same structure as your original table called t1. The following should get the job done:
TRUNCATE t1_temp; INSERT INTO t1_temp (id, power, tag) VALUES (SELECT id, SUM(power), tag FROM t1 GROUP BY tag); RENAME TABLE t1 TO t1_temp2, t1_temp TO t1, t1_temp2 TO t1_temp
However, I will recommend that you try to modify your insert statement. Create a unique index on tag and then use something like the following (assuming that id is auto-increment)
INSERT INTO t1 (power, tag) VALUES (3, 'option1') ON DUPLICATE KEY UPDATE power = power + 3
Even though you've already solved this is another approach
update your_table as t1
inner join
(select tag,sum(power) as power from your_table group by tag) as t2
set t1.power = t2.power
where t1.tag = t2.tag
alter ignore table your_table add unique index i (tag);
Related
I have two database table.Two table have same structure. Now i want to insert data from old table to new table if data already exists it will update the old data otherwise insert new. I want to insert or update data by matching some column field value. Any help?
You can make use of ON DUPLICATE KEY UPDATE feature of MySQL. From MySQL doc -
If you specify ON DUPLICATE KEY UPDATE, and a row is inserted that
would cause a duplicate value in a UNIQUE index or PRIMARY KEY, MySQL
performs an UPDATE of the old row.
So, if you have keys defined in the tables you can use this feature. For example, your statement will look like -
insert into target_table (col1, col2, ...)
select col1, col2,... from source_table
on duplicate key update
col1 = values(col1),
col2 = values(col2),
The Best way is you can use the left outer join concept.That will be easy.
INSERT INTO table1
(col_1, col_2, col_3, col_4, col_5) values("","","","")
SELECT
table2_col_1,
table2_col_2,
table2_col_3,
table2_col_4,
1
FROM
table_2 AS t2
LEFT OUTER JOIN
table1 AS t1
ON
t1.col_1 = t2.table2_col_1;
UPDATE table_2
SET table2_col_1 = 'value'// here is the value that you need to implement
WHERE t1.col_1=t2.table2_col_1;//here is your condition
From your Question , i understood that your table2 is not that much important.
So you can drop the values present in the entire table2 ,so that the structure will not get affected.After that was finished.. you can just export the insert query to implement the values that is present in the table1.
I have an sql query that simply adds a row to an existing database table. The first field is id and I assume this value has to be specified in the query.
So then id has to be the number of rows existing + 1. I'm determining the id like this:
SELECT COUNT(1) FROM testtable
The problem is that this returns the number of rows that have ever been added, including deleted ones. Because I have been adding and removing from this table, this number is greater than the number of EXISTING rows in the table which is what I want.
How can I count the existing rows in the table instead of the existing + deleted rows?
If possible switch to using an auto_increment column for your id and don't be concerned with gaps in the sequence of ids. Your own implementation of id generation may inflict more harm especially in a long run.
Now, back to your immediate question. You are probably looking for this
SELECT MAX(id) + 1 new_id
FROM Table1
Note: This query might fail under heavy load when several concurrent sessions issuing this
query might grab the same id and your subsequent INSERT will fail. Therefore again consider using an auto_increment for your id.
Here is SQLFiddle demo
That's a bad idea, because you can end up with duplicate IDs, especially if you delete rows in the middle. If you're not going to use an auto-increment field, you can add the ID to the insert. Just use this in place of the value:
((SELECT MAX(t.id) + 1 FROM table t)
The full query would then be:
INSERT INTO table_name (id, col1, col2, col3) VALUES ((SELECT MAX(t.id) + 1 FROM table_name t), :col1, :col2, :col3)
SELECT COUNT(*) from table
will return only the number of entries in it, not based on the ID
There is also possibility to find, and fill the gaps, by picking first free id
SELECT MIN(t1.id + 1) AS free_id
FROM t1
WHERE NOT EXISTS (SELECT t2.id FROM t2 WHERE t2.id = t1.id + 1)
SELECT id, FIO, parent_id
FROM users
WHERE parent_id =
(
SELECT id
FROM users
WHERE parent_id =
(
SELECT id
FROM users
WHERE id = 16
)
)
So here I am making an hierarchy tree, first selecting the root parent, then the children's and so on to 24th level of depth.
The question is: How to select more than one column from the inner queries?
Because I need to get the other rows fields to display info like: name, surname, age
It looks like I can only get those columns of rows in the outer query (the topmost).
P.S.: I don't want to use joins because they generate duplicate fields.
Is there a solution?
You could iterate on the SQL side using MySQL query variables. This will return all childs with all data of one parent node without repeating yourself (and thus without imposing a limit on the depth of your tree)
something like this: (500 being the parents id to start with)
SELECT
id,
parent_id,
name,
'0' as depth,
#tree_ids := id AS foo
FROM
tree,
(SELECT #tree_ids := '', #depth := -1) vars
WHERE id = 500
UNION
SELECT
id,
parent_id,
name,
#depth := IF(parent_id = 500, 1, #depth + 1) AS depth,
#tree_ids := CONCAT(id, ',', #tree_ids) AS foo
FROM
tree
WHERE FIND_IN_SET(parent_id, #tree_ids) OR parent_id = 500
See a working example at SQLfiddle
Note that this gives a really bad performance on larger datasets because MySQL will not use your indexes and instead will do a full table scan. (i don't understand why its not using indexes, thats just how it is. if someone has advice on or explain the indexing issue, please comment!)
= comparisons work on only a single value. You can use in to compare against multiple values:
SELECT ...
FROM yourtable
WHERE somefield IN (select somevalue from othertable);
Storing heirarchical data in mysql and getting it out is not as simple as that.
Look into this: https://stackoverflow.com/a/4346009/9094
You will need more data to work with.
It seems your DB relationship is setup to be MPTT, here is a good blog post exaplaining how to query mysql MPTT data
http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/
Have a look at Full Tree example Retrieving a Full Tree
in summary it can be done with joins.
I am not 100% sure if I understood exactly what you mean, but if you want to select all columns separately from the table in a subselect...
col1, col2, col3, col4
you would need for each column a single subselect that always matches against the same WHERE. Example:
`SELECT * FROM main_table,
(SELECT col1 FROM inner_table WHERE inner_table.some_column=main_table.some_column),
(SELECT col2 FROM inner_table WHERE inner_table.some_column=main_table.some_column), ...`
I have a table which has several thousand records.
I want to update all the records which have a duplicate firstname
How can I achieve this with a single query?
Sample table structure:
Fname varchar(100)
Lname varchar(100)
Duplicates int
This duplicate column must be updated with the total number of duplicates with a single query.
Is this possible without running in a loop?
update table as t1
inner join (
select
fname,
count(fname) as total
from table
group by fname) as t2
on t1.fname = t2.fname
set t1.duplicates = t2.total
I have a table which has several thousand records. I want to update all the records which have a duplicate firstname How can I achieve this with a single query?
Are you absolutely sure you want to store the number of the so called duplicates? If not, it's a rather simple query:
SELECT fname, COUNT(1) AS number FROM yourtable GROUP BY fname;
I don't see why you would want to store that number though. What if there's another record inserted? What if there are records deleted? The "number of duplicates" will remain the same, and therefore will become incorrect at the first mutation.
Create the column first, then write a query like:
UPDATE table SET table.duplicates = (SELECT COUNT(*) FROM table r GROUP BY Fname/Lname/some_id)
Maybe this other SO will help?
How do I UPDATE from a SELECT in SQL Server?
You might not be able to do this. You can't update the same table that you are selecting from in the same query.
I can't seem to grasp how I can select records when the records of one user span multiple rows.
Here is the schema of the table.
user_id key value
------------------------------------------
1 text this is sample text
1 text_status 0
2 text this is sample text
2 text_status 1
from the above table/row you can see that each user has info that has multiple rows. So in this case how do I select say "All the IDs, text value where text_status is "1"?
And to complicate it 1 step further, I need the email address of these accounts which is on another table. How can I write 1 select statement to pull in the email address as well? I know there is a JOIN statement for this but it's a bit complicated for me especially I can't even figure out the first part.
Added Note I must state that this table schema is a Wordpress default table wp_usermeta..
SELECT t1.*
FROM tbl t2
INNER JOIN tbl t1 ON t1.user_id = t2.user_id
AND t1.key = 'text'
WHERE t2.key = 'text_status'
AND t2.value = '1'
I think you've set up your table incorrectly. Make text_status and value exist within the same row.
The way it is right now, you would have to conduct two queries to get to your end result. Where as, the correct way needs only one.
This arbitrary key:value list scheme is alluring because of its flexibility. But it complicates queries obviously. Depending on the structure of your second table you could get away with:
SELECT key, value FROM user_table WHERE user_id=123
UNION ALL
SELECT 'email' as key, email as value FROM email_table WHERE user_id=123
But that pretty much only returns a list still, not a set of fields.
key and value looks wrong. SQL already gives you "key" (in the column name) and multiple "values" (in the values given per column in each row).
You've designed your table in a way that contravenes the way Database Management Systems are designed to work, which is leading to your problem. Read about database normalization.
Ideally your table would look something like this:
user_id text_status text
------------------------------------------
1 0 this is sample text
2 1 this is sample text
Then your query looks like:
SELECT `user_id`, `text` FROM `table` WHERE `text_status` = '1';
As your table stands now, you'll need something like (untested):
SELECT `table`.*
FROM `table` LEFT JOIN
(SELECT `user_id`
FROM `table`
WHERE `key` = "text_status"
AND `value` = "1"
) AS `_` USING(`user_id`)
WHERE `table`.`key` = "text"