Adding values in a column based on a query result - mysql

I have a table:---
id
name
dept
1
Alice
CS
2
Bob
Elect
3
David
Mech.
and a query result:-
id
count
1
100
2
22
3
50
Then I want to add the count column from the query to my original table, something like:-
id
name
dept
count
1
Alice
CSE
100
2
Bob
Elect
22
3
David
Mech.
50
The only I figured out to do, is by storing the query result into a new table and then using UPDATE...SET...WHERE. Is there any way to do it without creating a new table?

First you need to create the count column in tablename using
ALTER TABLE `tablename` ADD COLUMN `nr_count` INT;
Then use:
update tablename t
inner join ( SELECT id,
count(*) as nr_count
FROM tablename
GROUP BY id
) as t1
set t.nr_count=t1.nr_count ;

Related

MYSQL, How to compare ID with other column in the same table

I have a table in which I want to compare an ID column with another column in the same table.
This is my table
ID | Name | BossID
1 John 3
2 Max 4
3 Peter 4
4 Alex 5
For example I want to use
select * from mytable where ID = BossID
and I expected to get that Peter is the Boss of John and Alex is the Boss of Max and Peter, but when I use it this way, I dont get any info on the query...
Any idea to get it?
The expected query result are:
ID | Name | BossID
1 John 3
2 Max 4
3 Peter 4
seems like you want the list of employees who their boss exists in the list as well:
select *
from mytable
where bossid in (select id from mytable);
to get the boss name :
select t.ID, t.Name, b.Name as BossName
from mytable t
join mytbale b
on t.bossid = b.id
you can use left join to return all the employees in the list

Select only those rows that are in multiple result sets

I have multiple SELECT statements that all return the same columns but may return different resultsets. Is there any way to select all rows that are in all resultsets on database level?
E.g.
|---------------------|------------------|---------|
| ID | Name | Age |
|---------------------|------------------|---------|
| 1 | Paul | 50 |
| 2 | Peter | 40 |
| 3 | Frank | 20 |
| 4 | Pascal | 60 |
|---------------------|------------------|---------|
SELECT 1
SELECT name FROM table WHERE age > 40
Result: Paul, Pascal
SELECT 2
SELECT name FROM table where name like 'P%'
Result: Paul, Peter, Pascal
SELECT 3
SELECT name FROM table where id > 3
Result: Pascal
EDIT: This is a very simplified example of my problem. The statements can get very complex (joins over multiple tables), so a simple AND in the WHERE part is not the final solution.
The result should be Pascal. What I am looking for is something like a "reverse UNION".
Alternatively it would be possible to achieve that programatically (NodeJS), but I would like to avoid to iterate over all resultsets, because they might be quite huge.
Thanks in advance!
Is there any way to select all rows that are in all resultsets?
You seem to want and:
select name
from table
where age > 40 and name like 'P%' and id < 3
If using AND between the WHERE conditions is not possible, you could use multiple IN expressions on subqueries using your initial queries.
SELECT name
FROM table
WHERE id IN (SELECT id FROM table WHERE age > 40)
AND id IN (SELECT id FROM table where name like 'P%')
AND id IN (SELECT id FROM table where id < 3)
If you have different result sets and you want to see the intersection, you can use join:
select q1.id
from (<query 1>) q1 join
(<query 2>) q2
on q1.id = q2.id join
(<query 3>) q3
on q1.id = q3.id;
That said, I think GMB has the most concise answer to the question that you actually asked.
If your statements are complex, what you could do is to use a procedure where each of the statements put the matching id's into a temp table. Then select those rows where id's match the number of statements. This will also most likely be more efficient than one huge query with all complex statements combined into one.
create procedure sp_match_all()
begin
drop temporary table if exists match_tmp;
create temporary table match_tmp (
id int
);
insert into match_tmp
SELECT id FROM table WHERE age > 40;
insert into match_tmp
SELECT id FROM table where name like 'P%';
insert into match_tmp
SELECT id FROM table where id < 3;
select t.name
from table t
join (
select id
from match_tmp
group by id
having count(*)=3
) q on q.id=t.id;
drop temporary table match_tmp;
end

MySQL count occurrences but return all rows

Im trying to count occurrences of name, but i want each row returned no matter if that name has already been counted. The data looks like;
ID | NAME
1 Peter
2 Simone
3 Otto
4 Cedric
5 Peter
6 Cedric
7 Cedric
The following only returns one row per unique name
select id, first_name, count(first_name)from table group by first_name
ID | FIRST_NAME | count(first_name)
1 Peter 2
2 Simone 1
3 Otto 1
4 Cedric 3
But im trying to return every row, something like
ID | FIRST_NAME | count(first_name)
1 Peter 2
2 Simone 1
3 Otto 1
4 Cedric 3
5 Peter 2
6 Cedric 3
7 Cedric 3
If you are using MySQL version >= 8.0, then you can use window functions:
select id,
first_name,
count(*) over (partition by first_name)
from table
For earlier versions:
select id,
first_name,
(select count(*) from table where first_name = t.first_name)
from table t
You can use a Correlated subquery:
SELECT t1.id,
t1.first_name,
(SELECT COUNT(id)
FROM table t2
WHERE t2.first_name = t1.first_name) AS total_count
FROM table t1
Edit: now that I've seen the other answers, why is joining better than using a correlated subquery? Because a correlated subquery is executed for every row in your table. When you join it, the query is executed just once.
Then you have to join those queries.
select * from
table
inner join (
select first_name, count(first_name) as name_count from table group by first_name
) qcounts on table.first_name = qcounts.first_name
Also note, that in your query you have to remove id from the select clause, since you neither have it in your group by clause nor do you apply an aggregate function on it. Therefore a random row is returned for this column.
It's a good idea to let MySQL remind you of that by activating the only_full_group_by sql mode. To do this you can do
set global sql_mode = concat(##global.sql_mode, 'only_full_group_by');

mysql UPDATE query: add a table column with values

There are 3 columns in the table:
id Name Rating
1 John 0.976
2 Mark 0.500
3 Andrew 0.976
4 Jane 1.000
What sql query could be done to create a new id_new column to this table so id_new actually is the column that has the ordered by Rating?
So, the new table would be:
new_id id Name Rating
1 4 Jane 1.000
2 3 Andrew 0.976
3 1 John 0.976
4 2 Mark 0.500
You see this table looks like it was sorted desc by Rating.
How to do that using mySql query?
Thank you.
If you want to modify the structure of your table and add the new column:
ALTER TABLE `table_name` ADD `new_id` INT( 11 ) NOT NULL FIRST;
SET #new_id:=0;
UPDATE
table_name
SET
new_id = (#new_id := #new_id + 1)
ORDER BY
rating DESC;
If you don't want to modify the structure and just return a SELECT with the new column:
SET #new_id:=0;
SELECT
(#new_id := #new_id + 1) AS new_id,
id,
name,
rating
FROM
table_name
ORDER BY
rating DESC;
ALTER TABLE_NAME ADD new_id int(6) FIRST;

How to group by a field and return list of other field?

I have a table with columns id, user
I want to group by column id and show a list of users (comma separated) for each id.
In the final output I need to display:
user joe - id 1
users jim, mark, john - id 2
user dave - id 3
....
I'm getting error "Cardinality violation: 1242 Subquery returns more than 1 row" if I try this:
SELECT id, (SELECT distinct(user) FROM mytable b where a.id = b.id)
FROM mytable a
GROUP BY id
Since you are using MySQL, there is a built-in function for that which is the GROUP_CONCAT function. For example, you have a records like this:
ID User
1 Joe
2 Jim
2 Mark
2 John
3 Dave
If you try to run this query:
SELECT ID, GROUP_CONCAT(User) Users
FROM tableName
GROUP BY ID
you will then have a result like this:
ID Users
1 Joe
2 Jim, Mark, John
3 Dave
What you're looking for is the GROUP_CONCAT aggregate function:
SELECT id, GROUP_CONCAT(user) FROM table GROUP BY id