I have 3 tables in a database that have similar values and the same table structure. I am trying to get the number of occurrences of each value by unique user.
DB Structure
View on SQLFiddle
TABLE_1
user | value | id
TABLE_2
user | value | id
TABLE_3
user | value | id
I can run the following MySQL command to retrieve the desired results on 1 table at a time.
SELECT value,COUNT(*) as count FROM TABLE_1 GROUP BY value ORDER BY count DESC;
I need to run this command across the three tables at once in order to retrieve the unique occurrences of "value" among a list of "users" that contains numerous duplicates.
Given your comments, since you want to remove duplicates, use UNION to combine the data from the tables together:
SELECT value, COUNT(*) as count
FROM (
SELECT user, value, id
FROM TABLE_1
UNION
SELECT user, value, id
FROM TABLE_2
UNION
SELECT user, value, id
FROM TABLE_3 ) t
GROUP BY value
ORDER BY count DESC;
Updated Fiddle
You need to use UNION -
SELECT value, COUNT(*) as count
FROM (
SELECT user, value, id
FROM TABLE_1
UNION
SELECT user, value, id
FROM TABLE_2
UNION
SELECT user, value, id
FROM TABLE_3 ) tables
GROUP BY value
ORDER BY count DESC;
Output -
+-------+-----+
|car |8 |
|boat |4 |
|truck |3 |
|house |2 |
|skates |1 |
|bike |1 |
+-------+-----+
to go along with the comments this is what I would recommend you do.
setup:
CREATE TABLE members (
id int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
username varchar(255),
);
INSERT INTO members (username)
SELECT DISTINCT user FROM table1
UNION SELECT DISTINCT user FROM table2
UNION SELECT DISTINCT user FROM table3;
altering:
ALTER table1
ADD COLUMN user_id INT(10)
ADD INDEX `user_id` (`user_id`);
ALTER table2
ADD COLUMN user_id INT(10)
ADD INDEX `user_id` (`user_id`);
ALTER table3
ADD COLUMN user_id INT(10)
ADD INDEX `user_id` (`user_id`);
updating:
UPDATE table1 t,
JOIN members m ON m.username = t.username
SET t.user_id = m.id;
UPDATE table2 t,
JOIN members m ON m.username = t.username
SET t.user_id = m.id;
UPDATE table3 t,
JOIN members m ON m.username = t.username
SET t.user_id = m.id;
removing non normalized data
ALTER table1
DROP user;
ALTER table2
DROP user;
ALTER table3
DROP user;
now you can also set up foreign key contstraints on the user_id and id columns if you would like.
but to query a total count you can just join the tables.. make sure you add an index on each of the id fields so it will join properly.
SELECT your_stuff
FROM members m
LEFT JOIN table1 t1 ON t1.user_id = m.id
LEFT JOIN table2 t2 ON t2.user_id = m.id
LEFT JOIN table3 t3 ON t3.user_id = m.id
Related
I have a two different tables
Table 1
id
name
description
Table 2
id
details
info
table1_id
I want to display all the records from the table1 except id but from table2 I used to display the max id.
eg. table1 have following records
id=1
name = test
description = some text
table2 have
id=5
details = some more text
info = the new info
table1_id = 1
so the result what I want is
id name description
5 test some text
Try this:
select
(select max(table2.id) from table2 where table1.id = table2.table1_id) id,
name,
description
from table1
or left join:
select
t.id,
table1.name,
table1.description
from table1
left join (
select max(id) id, table1_id from table2 group by table1_id
) t on table1.id = t.table1_id
You can try with and max.
with ID_Table_1_MaxID_Table_2 as (
select table1_id, max(id) Max_Table2_ID
from Table_2
group by table1_id
)
SELECT tb2.id, tb1.name, tb1.description
FROM Table_2 tb2
INNER JOIN ID_Table_1_MaxID_Table_2 sub
ON (sub.table1_id = tb2.table1_id and tb2.id = sub.Max_Table2_ID)
INNER JOIN Table_1 tb1 on tb1.id = sub.table1_id
i have a comment table with this fields
id | user_id | parent_id
and a user table
id | username
how sholud i join this table with itself and user table to get parent comment user name?
SELECT comment.* ,c1.id as child_id,c1.user_id as child_user_id FROM `comment`
LEFT JOIN comment c1 ON c1.parent=comment.id
LEFT JOIN users ON users.id=child_user_id
in first join i get child_user_id which is a user id that i want it's user name But how can I join user table based on child_user_id?
Try something like this:
SELECT *,(
SELECT username FROM user WHERE id = a.parent_id
) parent_username
FROM comment a
JOIN user b on a.user_id = b.id
I have a few tables that each have their own scores for each user. I would like to create a trigger that will add up all those scores for each user and put them in a field called score in the users table.
Tables (They essentially have the same fields with a few different ones) :
Table 1 : {id, user_id, score}
Table 2 : {id, user_id, score}
Table 3 : {id, user_id, score}
users : {id, name, overall_score}
// Overall _score has a value already , so i just want to add the score fields from the other tables to this one.
To achieve this lets first write the select query and get sum of all the scores per user from the 3 given tables and this is how it could be done
select u.*, y.total from users u
left join
(
select user_id,sum(score) as total from(
select user_id, score from table_1
union all
select user_id, score from table_2
union all
select user_id, score from table_3
)x group by x.user_id
)y on y.user_id = u.id
Here is the demo http://www.sqlfiddle.com/#!9/6f936/1
Now lets convert the select to an update command and it will be as
update users u
left join
(
select user_id,sum(score) as total from(
select user_id, score from table_1
union all
select user_id, score from table_2
union all
select user_id, score from table_3
)x group by x.user_id
)y on y.user_id = u.id
set u.overall_score = coalesce(y.total,0)
here is the demo http://www.sqlfiddle.com/#!9/c6993/1
To select data from multiple tables, you can use SQL JOINS.
See the example below:
SELECT table1.score, table2.score, table3.score
FROM table1 LEFT JOIN table2
ON table1.id=table2.id LEFT JOIN table3 ON table1.id=table3.id
This code will select the score column from table1, table2, and table3 and create one row per user_id, each containing one score-column/ table (in this case 3/ row). It's almost like having a fourth table containing all the scores, and then when you fetch them in PHP, it'd be like fetching an existing row from the database.
EDIT:
To Update the users table in the same query, you could use something like this:
UPDATE `users`,
(
SELECT table1.id as tid, table1.score as t1,
table2.score as t2, table3.score as t3
FROM table1 LEFT JOIN table2 ON table1.id=table2.id
LEFT JOIN table3 ON table1.id=table3.id
) as total
SET total_score = (t1 + t2 + t3) WHERE id = tid
I have two tables in mysql table1 and table2
table1 have the following fields
Field Type
intProjectId int(11)
intSourceId int(11)
intClientId int(11)
varProject varchar(200)
fltAmount float
varAmountType varchar(50)
dtStart date
dtEnd date
And table 2 have the following fields
Field Type
intPercentageId int(11)
intProjectId int(11)
floatPaymentpercentage float
ddDate datetime
join two table with common project id.If table2 has no records with the particular project id it can joined as null..
Table 1 has project data
Table 2 has its percentage of complettion. (Each project has more than one records. )
Project Id -- common field
Iused the following query
SELECT * FROM table1 LEFT OUTER JOIN table2 ON table1.intProjectId = table2.intProjectId
GROUP BY table1.varProject ORDER BY table2.intPercentageId DESC
Here i get the output as percentage table returns the first record for each project. I need the last inserted record for the table 2.
table1 ==> project id 5
In table 2 has 3 records for project Id 5. I want to ge the last record from the table2. Now it returns the first record from table 2
How to change the query. Please help me to fix this.
Calculate the maximum record for each project in table2 and use that information to get the latest record. Here is a method that uses group by:
select t1.*
from table1 t1 join
table2 t2
on t1.intProjectId = t2.intProjectId join
(select t2.intProjectId, max(intPercentageId) as maxpi
from table2 t2
group by t2.intProjectId
) tt2
on t2.intProjectId = tt2.maxpi;
Calculate the maximum record for each project in table2 and use that information to get the latest record. Here is a method that uses group by:
select t1.*
from table1 t1 join
table2 t2
on t1.intProjectId = t2.intProjectId join
(select t2.intProjectId, max(intPercentageId) as maxpi
from table2 t2
group by t2.intProjectId
) tt2
on t2.intProjectId = tt2.maxpi;
Try this
SELECT * FROM table1 LEFT OUTER JOIN table2 ON table1.intProjectId = table2.intProjectId
GROUP BY table1.varProject HAVING MAX(table2.intPercentageId)
"Order By" runs after "Group by" has completed, that is why it is not giving the intended result. The change I have suggested will give the row from 2nd table with the highest percentage which as per the scenario should be the last row for the project.
I have a table that contains results from football matches between two teams. Firstly I want to have a drop down menu of the teams. This should be simply something like SELECT * FROM table GROUP BY Team_A
But a team could be missed if they only ever appear in the Team_B column. Is it possible to group columns Team_A and Team_B so that I could output all unique teams across both columns?
If you want all the names, then use union. This also removes duplicates:
select TeamA from table union
select TeamB from table
This will give you the right data, but . . .
select team_a as team_name
from test
union
select team_b
from test
order by team_name;
You should probably have foreign key references to a table of teams. If you had that, with the obligatory unique constraint on the team's name, you'd just need to
select team_name
from teams
order by team_name;
Use a UNION like this:
SELECT Team_A AS TeamName FROM table
UNION ALL
SELECT Team_B AS TeamName FROM table
to get the distinct listing of teams. But I have to say, you really need to restructure your database. You should have a table like this:
CREATE TABLE Teams (
ID INT PRIMARY KEY IDENTITY(1, 1),
Name VARCHAR(50) NOT NULL UNIQUE
)
and then a table like this:
CREATE TABLE Scores (
ID INT PRIMARY KEY IDENTITY(1, 1),
HomeTeamId INT NOT NULL,
AwayTeamId INT NOT NULL,
HomeTeamScore INT NOT NULL,
AwayTeamScore INT NOT NULL
)
and that would allow not only a more straight forward selection of teams:
SELECT Name FROM Teams
but it would also build some real database integrity because you could build foreign keys and you wouldn't be using simple string values to indicate key values.
Don't you just mean:
group by Team_A, Team_B
?
This will group by the combination of Team_A and Team_B
edit: To end up with TWO columns, each having a unique list of teams that already existed in that column (exactly as described by OP):
SELECT a.*, b.* FROM
(SELECT Team_A, #ida := ifnull(#ida,0) + 1 AS ida FROM table GROUP BY Team_A) AS a
LEFT JOIN
(SELECT Team_B, #idb := ifnull(#idb,0) + 1 AS idb FROM table GROUP BY Team_B) AS b
ON a.ida=b.idb
and isnull(#ida := null) and isnull(#idb := null) -- reset #ida and #idb
UNION ALL -- turn the left and right join into full outer join
SELECT c.*, d.* FROM
(SELECT Team_A, #idc := ifnull(#idc,0) + 1 AS idc FROM table GROUP BY Team_A) AS c
RIGHT JOIN
(SELECT Team_B, #idd := ifnull(#idd,0) + 1 AS idd FROM table GROUP BY Team_B) AS d
ON c.idc=d.idd
and isnull(#idc := null) and isnull(#idd := null) -- reset #idc and #idd
WHERE c.idc is null -- prevent doubles in the full outer join