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
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
Okay so I have three(3) tables that i want to join together
tableA is the main details and primary key is row_id autoincremented
tableB is the exteded details and primary/foreign key is row_id coming from tableA
tableC stores unordered ratings and comments for a particular row_id
I want to join all these tables so that I can see all details plus the number of instances in tableC for a row_id and the avg rating.
SELECT *
FROM `tableA` A
LEFT JOIN `tableB` B
ON A.`row_id` = B.`row_id`
LEFT JOIN (
SELECT COUNT( 1 ) AS 'count', Avg(`row_rating`) AS 'avg'
FROM `tableC`
GROUP BY tableC.`row_id`
)C
ON C.`row_id` = A.`row_id`
ORDER BY C.`avg` ASC
The result of this query combines all properly but the same count and avg is displayed in all rows.
Looks like you want to group the records by row_id in inner query. In which case, you need to SELECT row_id instead of COUNT(1), try this:
SELECT *
FROM `tableA` A
LEFT JOIN `tableB` B
ON A.`row_id` = B.`row_id`
LEFT JOIN (
SELECT row_id, Avg(`row_rating`) AS 'avg'
FROM `tableC`
GROUP BY tableC.`row_id`
)C
ON C.`row_id` = A.`row_id`
ORDER BY C.`avg` ASC
I have Problems with a select statement, as a little help here are the important columns:
Table1
ID NAME
TABLE 2
ID U_ID COUNTER
The ID of Table 1 Matches the U_ID of Table 2. Table 2 contains many entries for the same u_id.
What I want to do is to get the Name of the "user" (table 1) who has in sum the max. counter.
What I got since now is the join of the tables (Where clause depends on other rows which are not important for the problem).
Can anyone help me on this issue?
So what you need is an aggregate of an aggregate (max of sum of column). The easiest will be to create a view providing the sum and u_id end then select the max of it:
create view table2sums
as
select u_id, sum(counter) as total
from table2
group by u_id;
and then
select t1.name
from table1 t1, table2sums t2
where t1.id = t2.u_id
and t2.total >= all (
select total
from table2sums
)
In this special case you can also do it directly:
select t1.name
from table1 t1, table2 t2
where t1.id = t2.u_id
group by t1.name
having sum(t2.counter) >= all (
select sum(counter)
from table2
group by t2.u_id
)
NOTE: The other proposed solutions will show a better performance. My solution only selects the name (which is what you said you wanted) and works in any RDBMS.
There exist RDBMS without the LIMIT possibility.
In the end, I'd say: regard my solution as educational, the others as practical
SELECT name,
SUM(counter) as counter
FROM table1
JOIN table2
ON table1.id = table2.u_id
GROUP BY u_id
ORDER BY counter DESC
LIMIT 1
You can try this:
SELECT name, SUM(counter) as total_counter
FROM table1
JOIN table2
ON table1.id = table2.u_id
GROUP BY u_id
ORDER BY total_counter DESC
LIMIT 1
Working Demo: http://sqlfiddle.com/#!2/45419/4
I have two tables Table1 and Table2 with some records
id is the common column in both tables and primarykey is set to this column in table1
There are many records in table1 and some of these records (not all) are updated into table2.
Now I want retrieve from table1 the records not updated into the table2.
For example in table1 there are records 1,2,3,4,5,6,7,8,9
And in table2 there are 3,4,7,9
Now How can I retrieve these records form table1 1,2,5,6 those not updated into table2
I wrote this query :
SELECT Table1.id, Table1.DATE, Table1.C_NAME, Table1.B_NAME
FROM [Table1] INNER JOIN Table2 ON Table1.SLIPNO <>Table2.id;
But the expected result not coming. This query lists all the records repeating each one record manytimes
Can any body give me solution to get the expected result.
select *
from table1
where table1.slip_no NOT IN (select id from table2)
Assuming name of common column is id
Or you can modify your query as
SELECT distinct (Table1.id, Table1.DATE, Table1.C_NAME, Table1.B_NAME)
FROM [Table1]
INNER JOIN Table2 ON Table1.SLIPNO <>Table2.id
A good reference on SQL joins
SELECT t1.*
FROM table1 AS t1
LEFT OUTER JOIN table2 AS t2 USING(id)
WHERE
t2.id IS NULL;
You can use the NOT IN operator on a subquery for table2.
Alternatively, use MINUS with two regular queries listing the ids in each table:
SELECT id FROM table1
MINUS
SELECT id FROM table2;
Try this
SELECT Table1.id, Table1.DATE, Table1.C_NAME, Table1.B_NAME FROM [Table1]
WHERE
NOT EXISTS (SELECT * from Table2 WHERE Table1.SLIPNO !=Table2.id );
You can use the following query
SELECT id FROM database1.table WHERE id NOT IN(SELECT id FROM database2.table)
SELECT child_table.id FROM child_table LEFT JOIN parent_table ON child_table.parent_id = parent_table.id WHERE parent_table.id IS NULL
This left join query returns all the records of the child_table when there is no match in the parent_table. When there is no match, all parent_table fields will be NULL.
inner join will not help. To get unmatched records I tried this:
SELECT
A.ID,A.DATE,A.NAME
FROM TABLE1 A
WHERE CONCAT(A.ID , A.DATE ,A.NAME)
NOT IN
(SELECT CONCAT(B.ID , B.DATE ,B.NAME) as X
from TABLE2 B) ;
I have 3 tables.
table1
id, thing_id
table_index
id
table_index_info
table_index_id, table1_id
table_index_info contains a history of table_index. This history can refer to table1, possibly many times or 0 times.
I need to run a query that returns all rows in table1 with a specific thing_id.
It also needs to count how many rows in table_index that have at least 1 table_index_info linking to table1.
Here's my query:
SELECT table1.*,
(SELECT COUNT(i.id)
FROM table_index i
WHERE EXISTS (SELECT 0
FROM table_index_info h
WHERE h.table1_id = table1.id
AND h.table_index_id = i.id)
) AS indexCount
FROM table1
WHERE table1.thing_id= $thingId
Is this the best/correct way to do this?
I would use a JOIN instead of EXISTS in this case.
SELECT table1.*,
( SELECT COUNT(i.id)
FROM table_index i
INNER JOIN table_index_info h ON h.table_index_id = i.id
WHERE h.table1_id = table1.id
) AS indexCount
FROM table1
WHERE table1.thing_id = $thingId