mysql Update table after querying from it - mysql

I have a table filled with first and last names. I have two other columns that I am trying to update. These two columns has the number of people that have the same first names and same last names. For example,
first last samef samel
John Smith 1 2
John Adams 1 1
Mary Kate 0 0
Kate Adams 2 1
Kate Smith 2 2
Kate Smith 2 2
Alice Mirth 0 0
So far I can only come up with these two queries, but of course they are not correct. They return the total count for each name when I need the total count - 1. Plus, the results are shown on separate tables.
I was wondering if I should use a stored procedure where I use variables to store the count for samef and samel. And then insert it into the names table, but I don't know the correct syntax for this.
SELECT first, last,
( SELECT COUNT(*) FROM names WHERE first = table1.first) AS samef
FROM names AS table1
SELECT first, last,
( SELECT COUNT(*) FROM names WHERE last = table2.last) AS samel
FROM names AS table2
I am new to mySQL so please provide explanations.

Just like Strawberry mentioned, do not store information that can be derived. Databases are great at storing data optimally. SQL is great at extracting table and derived/calculated data. Try this:
select `first`, `last`,
(select count(*)-1 from test where `first` = t.`first`) as samef,
(select count(*)-1 from test where `last` = t.`last`) as samef
from test t;
Example: http://sqlfiddle.com/#!9/9c673f/1
Result:
| first | last | samef | samef |
|-------|-------|-------|-------|
| john | smith | 1 | 2 |
| john | adams | 1 | 1 |
| mary | kate | 0 | 0 |
| kate | adams | 2 | 1 |
| kate | smith | 2 | 2 |
| kate | smith | 2 | 2 |
| alice | mirth | 0 | 0 |

Related

How to select a column's value, only if all other entries with the same value exist and match? (MYSQL)

The title is a bit messy, but here's an example
suppose we have table:
| name | room |
=================
| John | 4 |
| John | 6 |
| John | 9 |
| Smith | 4 |
| Smith | 6 |
| Brian | 4 |
| Brian | 6 |
| Brian | 9 |
I want to select John and Brian because they both have exactly rooms 4, 6 and 9, but not Smith, since he doesn't have the room 9. (If we had another person who ONLY has room 4 and 6, then it'd select that other person as well as Smith).
I know I need to do some kind of correlated query, but I'm not sure how to actually get it to do something like
for a check for b
If you want groups of names that share the exact same rooms, I would recommend group_concat():
select rooms, group_concat(name) as names
from (select name, group_concat(room order by room) as rooms
from t
group by name
) n
group by rooms;
If you want only combinations with more than one name, then add having count(*) > 1 to the outer select.

How to count unique items in column in Access

I need help. I can't seem to find the logic behind this code.
I am working on a voting system, and I need to output the results of the votes.
I want to count all of the rows that has a unique name in it and output how many.
My table goes like this.
voterid | pres | vpres | sec | trea | PIO
---------------------------------------------
1 | John | Mitch | James | Jack | Eman
2 | John | Pao | Bryan | Jack | Faye
3 | Kelvin | Pao | James | Jeck | Faye
Output should be
Pres | Votes
--------------
John | 2
Kelvin | 1
Here's my code.
SELECT DISTINCT
pres,
(SELECT COUNT(pres) FROM (SELECT DISTINCT pres FROM tblVote AS Votes)) AS Votes
FROM tblVote
Thanks in advance!
I think you are just looking for a simple GROUP BY query:
SELECT pres, COUNT(*) AS Votes
FROM tblVote
GROUP BY pres

How do I backfill missing mysql data from one table?

I have a MySQL table called employee that looks like this:
ID | User | Phone_No | Phone_No_Count
1 | Fred | 9999 | 1
2 | John | 8888 | 2
3 | Pablo | 123 | 1
4 | John | | 0
5 | John | 8888 | 2
6 | Pablo | | 0
7 | John | 456 | 1
Phone_No_Count is a count of the Phone_No column, if there is no Phone_No then Phone_No_Count is set to zero.
I want to backfill the missing Phone_No entries using Phone_No entries which have the highest Phone_No_Count.
e.g. User John has 2 Phone_No's (8888 and 456) so I just want to use 8888 as it has the highest Phone_No_Count (2)
The backfilled data in employee would then look like this:
ID | User | Phone_No | Phone_No_Count
1 | Fred | 9999 | 1
2 | John | 8888 | 2
3 | Pablo | 123 | 1
4 | John | 8888 | 0
5 | John | 8888 | 2
6 | Pablo | 123 | 0
7 | John | 456 | 1
I can then update the Phone_No_Count separately, which I know how to do anyway.
All the examples I've seen online are for backfilling multiple tables or if it's just one table they don't have the required logic for this.
Can somebody please help as this has been frying my brain all day!!
One way to go about this kind of update you can use user defined variables in your query and store the phone for the user which has the maximum of phone count (i.e a correlated subquery) then join this data with your table and do update
update Table1 t1a
inner join(
select t1.id,
t1.`User`,
#p:= case
when t1.Phone_No is null then #c
else t1.Phone_No END Phone_No,
#c:=(select Phone_No from Table1 where t1.`User`=`User` order by `Phone_No_Count` DESC limit 1 ) max_phone
from Table1 t1,(select #p:=0,#c:=0) t
order by t1.`User`,t1.`Phone_No_Count` DESC
) t2 on(t1a.id=t2.id)
set t1a.Phone_No = t2.Phone_No
Fiddle Demo
The trick is to get the phone number for the highest count. Unfortunately, MySQL doesn't let you have subqueries on the same query being updated, but you can do this with a trick. This allows you to use update/join syntax:
update employee e join
(select e.user,
substring_index(group_concat(phone_no order by phone_no_count desc
), ',', 1) as new_phone_no
from employee e
group by e.user
) toupdate
on e.user = toupdate.user
set e.phone_no = toupdate.new_phone_no
where e.phone_no is null;

SQL - select a list of lists

So I have a table where each row may or may not be merged via a merge_id.
Its easy to jump in and grab all merged rows, where the merge_id column is not null. The thing is I want to output the merged rows together in one container on the client side.
I there any way for sql to return a collection for merged collections ?
Do I sort in ascending order of the merge ID and trust that its sequential ?
EDIT
________________________________________________
|id | firstname | lastName | merge_id |
|------------------------------------------------|
| 1 | jane | Doe | 1 |
-------------------------------------------------|
|------------------------------------------------|
| 2 | John | Doe | 1 |
-------------------------------------------------|
|------------------------------------------------|
| 3 | max | payne | 2 |
-------------------------------------------------|
|------------------------------------------------|
| 4 | sub | zero | 3 |
--------------------------------------------------
So I want to query in such a way that I know that jane and max belong to different mergers.
How about
SELECT firstname, lastname, merge_id
FROM table t
ORDER BY t.merge_id
That would give you a record per person, and the merge_id will be ascending:
1 | Jane Doe
1 | John Doe
2 | max payne
3 | sub zero
Otherwise, you can use GROUP_CONCAT:
SELECT merge_id , GROUP_CONCAT(CONCAT(firstname, ' ', lastname))
FROM table t
GROUP BY t.merge_id
ORDER BY t.merge_id
Which will give one record per merge_id:
1 | Jane Doe, John Doe
2 | max payne
3 | sub zero

Use MySQL to create a string out of a subquery?

What I'm hoping to do is create a string out of a table WITHIN a query so that I may be able to place that string in another query I'm creating. Say, I have this for a table:
index | position | name
----------------------------------------
1 | member | John Smith
2 | chair | Mary Jones
3 | member | Mary Jones
4 | contact | Grace Adams
5 | director | Grace Adams
6 | member | Grace Adams
7 | treasurer | Bill McDonnell
8 | vice chair | Bill McDonnell
9 | member | Ishmael Rodriguez
I'm looking for the result as follows:
name | positions
----------------------------------------
John Smith | member
Mary Jones | chair,member
Grace Adams | contact,director,member
Bill McDonnell | treasurer,vice chair
Ishmael Rodriguez | member
I was hoping I could use some variant of CONCAT_WS() to get my result, like this...
SELECT
a.NAME,
CONCAT_WS(
',',
(
SELECT
position
FROM
TABLE
WHERE
NAME = a.NAME
)
)AS positions FROM ---------------
Obviously, this isn't working out for me. Any ideas?
Use GROUP_CONCAT[docs]
SELECT name, GROUP_CONCAT(position) result
FROM tableName
GROUP BY name
ORDER BY `index`
SQLFiddle Demo
Use GROUP_CONCAT like so:
SELECT name, GROUP_CONCAT(position SEPARATOR ',')
FROM Table
GROUP BY name