I have 2 table as below:
Table 1: common_member
+-----------+-----------+
| uid | username |
+-----------+-----------+
| 1 | haha |
| 2 | walao |
| 3 | alamak |
| 4 | hero |
| 5 | theone |
| 6 | nobody |
+-----------+-----------+
Table 2: labour_slog
+--------------+-------------+--------------+-------------+
| uid | slaveid | masterid | bytime |
+--------------+-------------+--------------+-------------+
| 1 | 2 | 3 | 123456 |
| 4 | 5 | 6 | 456789 |
+--------------+-------------+--------------+-------------+
I fetch the data as script below:
$queryLabourSlog = DB::query("SELECT * FROM ".DB::table('labour_slog')." ORDER BY id desc");
while($rowLabourSlog = DB::fetch($queryLabourSlog)) {
$user_list_slog[] = $rowLabourSlog;
};
array_multisort($idss, SORT_DESC, $user_list_slog);
In my html, I use
<!--{loop $user_list_slog $value}-->{$value[uid]} on {$value[bytime]} forced hire {$value[masterid]}'s employee {$value[slaveid]}.<!--{/loop}-->
The html will display:
1 on 123456 forced hire 3's employee 2.
4 on 456789 forced hire 6's employee 5.
How do I join the Table 1's username data to get the loop display as below?
haha on 123456 forced hire alamak's employee walao.
hero on 456789 forced hire nobody's employee theone.
Thanks.
SELECT table_slog.*, u1.`name`, u2.`name` FROM `table_slog` LEFT JOIN `common_member` AS u1 ON `table_slog`.`uid`=u1.`uid` LEFT JOIN `common_member` AS u2 ON `table_slog`.`slaveid`=u2.`uid` LEFT JOIN `common_member` AS u3 ON `table_slog`.`masterid`=u3.uid ORDER BY `id` DESC
Something like that:
SELECT `uid_main`.`username` AS `main_username`,
`uid_main`.`uid` AS `main_uid`,
`uid_master`.`username` AS `master_username`,
`uid_master`.`uid` AS `master_uid`,
`uid_slave`.`username` AS `slave_username`,
`uid_slave`.`uid` AS `slave_uid`,
`ls`.`bytime` AS `bytime`
FROM `labour_slog` AS `ls`
LEFT JOIN `common_member` AS `uid_main` ON (`ls`.`uid` = `cm`.uid)
LEFT JOIN `common_member` AS `uid_master` ON (`ls`.`master_id` = `cm`.uid)
LEFT JOIN `common_member` AS `uid_master` ON (`ls`.`slave_id` = `cm`.uid)
ORDER BY `cm`.`uid` DESC
Related
i have this 4 tables
table FRUIT, ID is Primary key
| ID | code | A | B |
--------------------------------------------
| 1 | a01 | apple1 | quava1 |
| 2 | a02 | apple2 | quava2 |
table FLOWER, ID is Primary key
| ID | code | C | D |
--------------------------------------------
| 1 | a01 | Rose1 | Plumer1 |
| 2 | a02 | Rose2 | Plumer2 |
table ANIMAL, ID is Primary key
| ID | code | E | F |
--------------------------------------------
| 1 | a01 | butterfly1 | cat1 |
| 2 | a02 | butterfly2 | cat2 |
table DAY, code is Primary key
| code | G |
-------------------------------------
| a01 | Monday |
| a02 | Tuesday|
i want to call and combined those 4 tables into like this
| ID | A | B | C | D | E | F | G |code |
--------------------------------------------------------------------------------
| 1 | apple1 | quava1 | Rose1 | Plumer1 |butterfly1 | cat1 |Monday |a01 |
| 2 | apple2 | quava2 | Rose2 | Plumer2 |butterfly2 | cat2 |Tuesday |a02 |
this is the code:
SELECT day*, fruit*, flower*, animal*
FROM day
LEFT JOIN fruit
ON day.code = fruit.code
LEFT JOIN flower
ON day.code = flower.code
LEFT JOIN flower
ON day.code = animal.code
ORDER BY day.code DESC;
it is said that column code is ambiguous. and cannot show the table.
i need help. how can i fix this?
I would do it in this manner, using Aliases and JOINs to join all the tables (including the animal table which you forgot), and of course not forgetting to include the periods . where needed:
SELECT fr.ID, fr.A, fr.B, fl.C, fl.D, a.E, a.F, d.G, fr.code
FROM `day` AS d
LEFT JOIN `fruit` AS fr ON d.code = fr.code
LEFT JOIN `flower` AS fl ON d.code = fl.code
LEFT JOIN `animal` AS a ON d.code = a.code
ORDER BY d.code ASC;
you forget to add . between column_name and * like day.*
Try This
SELECT `day`.*, fruit.*, flower.*, animal.*
FROM `day`
LEFT JOIN fruit
ON `day`.code = fruit.code
LEFT JOIN flower
ON `day`.code = flower.code
LEFT JOIN flower
ON `day`.code = animal.code
ORDER BY `day`.code DESC;
Beside the fact that you forgot a dot '.' between the table name and the *, thats becuase you are selecting id and code column from each table, you need to specify where are you selecting from when there is more then 1 options :
SELECT fruit.A,fruit.B, flower.C,flower.D, animal.E,animal.F,day.G,day.code
FROM day
LEFT JOIN fruit
ON day.code = fruit.code
LEFT JOIN flower
ON day.code = flower.code
LEFT JOIN animal
ON day.code = animal.code
ORDER BY day.code DESC;
My database looks something like this, in order of user, userteam (connection table) and team:
Usertable UserTeam Teamtable
+--------+------+ +--------+--------+ +--------+-------+
| userid | name | | userid | teamid | | teamid | name |
+--------+------+ +--------+--------+ +--------+-------+
| 1 | eric | | 1 | 1 | | 1 | awsm |
| 2 | john | | 1 | 2 | | 2 | doe |
| 3 | carl | | 2 | 1 | | 3 | empty |
+--------+------+ | 3 | 1 | +--------+-------+
+--------+--------+
How do I select all users that IS NOT in a team, and echo them out only once? I've tried doing it with the usertable, but then it will echo for instance, if I try and select all members not in team 3:
SELECT userid FROM userteam WHERE teamid!=3;
SELECT * FROM user WHERE userid='$previousSql';
1 eric
1 eric
2 john
3 carl
What I'd like instead is:
1 eric
2 john
3 carl
I'm making an add members function, and I'd very much not like everyone to show up more than once.. Any directions, help or guiding would be much appreciated.
add
GROUP BY name
to the query
This should do it:
SELECT u.userid, u.name FROM Usertable u
INNER JOIN UserTeam ut ON ut.userid = u.userid
INNER JOIN Teamtable tt ON tt.teamid = ut.teamid
WHERE tt.teamid != 3
GROUP BY u.userid, u.name;
SELECT userid, name FROM usertable
JOIN userteam ON userteam.userid = usertable.userid
JOIN teamtable on teamtable.teamid = userteam.teamid
WHERE teamtable.teamid = 3;
The SQL above should do the proper joins between all the tables and then will only list the userid/names of people who have a teamid of 3 in the teamtable
EDIT* Removed ! from WHERE clause.
I have a tables like this:
Users
+----+----------+-------------+
| id | name | other_stuff |
+----+----------+-------------+
| 1 | John Doe | x |
| 2 | Jane Doe | y |
| 3 | Burt Olm | z |
+----+----------+-------------+
Places
+----+------------+-------------+
| id | name | other_stuff |
+----+------------+-------------+
| 1 | Building A | x |
| 2 | Building B | y |
+----+------------+-------------+
Subjects
+----+------------+-------------+
| id | name | other_stuff |
+----+------------+-------------+
| 1 | Math | x |
| 2 | English | y |
+----+------------+-------------+
And a joining table:
PastLectures = lectures that took place
+----+-----------+----------+------------+---------+------------+
| id | id_users | id_place | id_subjects| length | date |
+----+-----------+----------+------------+---------+------------+
| 1 | 1 | 1 | 1 | 60 | 2015-10-25 |
| 2 | 1 | 1 | 1 | 120 | 2015-11-06 |
| 3 | 2 | 2 | 2 | 120 | 2015-11-04 |
| 4 | 2 | 2 | 1 | 60 | 2015-11-10 |
| 5 | 1 | 2 | 1 | 60 | 2015-11-10 |
| 6 | 2 | 2 | 1 | 40 | 2015-11-15 |
| 7 | 1 | 2 | 2 | 30 | 2015-11-15 |
+----+-----------+----------+------------+---------+------------+
I would like to display SUM of all lessons for each user for given month. The SUM should by grouped by each Places and Subjects.
The result in final PHP output should look like this:
November 2015
+------------+-------------+---------------+-------------+
| Users.name | Places.name | Subjects.name | sum(length) |
+------------+-------------+---------------+-------------+
| Burt Olm | - | - | - |
| Jane Doe | Building B | Math | 100 |
| = | = | English | 120 |
| John Doe | Building A | Math | 120 |
| = | Building B | Math | 60 |
| = | = | English | 30 |
+------------+-------------+---------------+-------------+
I have tried creating the full output in pure SQL query using multiple GROUP BY (Group by - multiple conditions - MySQL), but when I do GROUP BY User.id,Places.id it shows each user only once (3 results) no matter the other GROUP BY conditions.
SQL:
SELECT PastLectures.id_users,Users.name AS user,Places.name AS places,Subjects.name AS subjects
FROM PastLectures
LEFT JOIN Users ON PastLectures.id_users = Users.id
LEFT JOIN Places ON PastLectures.id_Places = Places.id
LEFT JOIN Subjects ON PastLectures.id_Subjects = Subjects.id
WHERE date >= \''.$monthStart->format('Y-m-d H:i:s').'\' AND date <= \''.$monthEnd->format('Y-m-d H:i:s').'\'
GROUP BY Users.id,Places.id
ORDER BY Users.name,Places.name,Subjects.name
But I don't mind if part of the solution is done in PHP, I just don't know what to do next.
EDIT:
I also have a table Timetable, that stores who regularly teaches what and where. It stores only used combinations of the tables (each valid combination once).
Timetable = lectures that regularly take place
+----+-----------+----------+------------+-------------+
| id | id_users | id_place | id_subjects| other_stuff |
+----+-----------+----------+------------+-------------+
| 1 | 1 | 1 | 1 | x |
| 2 | 1 | 2 | 1 | y |
| 3 | 1 | 2 | 2 | z |
| 4 | 2 | 2 | 1 | a |
| 5 | 2 | 2 | 2 | b |
+----+-----------+----------+------------+-------------+
Is it possible to add only users with combinations that have a row in this table?
In this case it would mean omitting Burt Olm (no id=3 in Timetable). But if Burt has a Timetable entry and still no PastLectures entry, he would show here as in sample result (he should have had a lecture that month, because he is in Timetable, but no lectures took place).
Based on #Barmar's solution I updated the final SQL by making Timetable a primary table and adding one more LEFT JOIN to suffice those needs.
Final SQL:
SELECT Users.name AS user,Places.name AS places,Subjects.name AS subjects, SUM(PastLectures.length)
FROM Timetable
LEFT JOIN PastLectures ON PastLectures.id_users = Timetable.id_users AND PastLectures.id_place = Timetable.id_place AND PastLectures.id_subjects = Timetable.id_subjects
AND date BETWEEN '2015-11-01 00:00:00' AND '2015-11-30 23:59:59'
LEFT JOIN Places ON Timetable.id_Place = Places.id
LEFT JOIN Subjects ON Timetable.id_Subjects = Subjects.id
LEFT JOIN Users ON Timetable.id_users = Users.id
GROUP BY Timetable.id,Timetable.id_users,Timetable.id_Place,Timetable.id_Subjects
ORDER BY Users.name,Places.name,Subjects.name
You need to include Subjects.id in the GROUP BY, so you get a separate result for each subject.
Also, you shouldn't use columns in tables that are joined with LEFT JOIN in the GROUP BY column. If you do that, all the non-matching rows will be grouped together, because they all have NULL in that column. Use the columns in the main table.
GROUP BY PastLectures.id_users, PastLectures.id_Place, PastLectures.id_Subjects
DEMO
Note that there's no row for Burt Olm in the demo output, because all his rows are filtered out by the WHERE clause. If you want all users to be shown, you should make Users the main table, not PastLectures. And the date criteria needs to be moved into the ON clause when joining with PastLectures.
SELECT Users.name AS user,Places.name AS places,Subjects.name AS subjects, SUM(length)
FROM Users
LEFT JOIN PastLectures ON PastLectures.id_users = Users.id
AND date BETWEEN '2015-11-01 00:00:00' AND '2015-11-30 23:59:59'
LEFT JOIN Places ON PastLectures.id_Place = Places.id
LEFT JOIN Subjects ON PastLectures.id_Subjects = Subjects.id
GROUP BY Users.id, PastLectures.id_Place, PastLectures.id_Subjects
ORDER BY Users.name,Places.name,Subjects.name
DEMO
According to standard SQL, you should GROUP BY all the fields you select, except for the aggregated fields (like sum). Althought MySql allows to do otherwise, when it can be done adhering to the standards, it is better to do so (who knows when you need to port your code to another database engine). So write your SQL like this:
SELECT PastLectures.id_users,
Users.name AS user,
Places.name AS places,
Subjects.name AS subjects,
Sum(length)
FROM PastLectures
LEFT JOIN Users ON PastLectures.id_users = Users.id
LEFT JOIN Places ON PastLectures.id_Places = Places.id
LEFT JOIN Subjects ON PastLectures.id_Subjects = Subjects.id
WHERE date BETWEEN \''.$monthStart->format('Y-m-d H:i:s').'\'
AND \''.$monthEnd->format('Y-m-d H:i:s').'\'
GROUP BY PastLectures.id_users,
Users.name,
Places.name,
Subjects.name
ORDER BY Users.name,
Places.name,
Subjects.name
I have 2 tables in database:
How can I get total user for each group. i.e: group 1: total are 2 users;
group2: total are 2 users;
group3: total is 1 user
You need normalization and never store comma-separated data.
Consider the following
mysql> select * from user_table ;
+---------+---------------+
| user_id | user_group_id |
+---------+---------------+
| 1 | 1,2 |
| 2 | 2 |
| 3 | 1,3 |
+---------+---------------+
3 rows in set (0.00 sec)
mysql> select * from group_table ;
+----------+------------+
| group_id | group_name |
+----------+------------+
| 1 | a |
| 2 | b |
| 3 | c |
+----------+------------+
3 rows in set (0.00 sec)
The above data is not normalized and to get the desired result out of these you need to use some in-efficient query as
select
g.group_id,
count(*) as total
from group_table g
left join user_table u on find_in_set(g.group_id,u.user_group_id) > 0
group by g.group_id ;
+----------+-------+
| group_id | total |
+----------+-------+
| 1 | 2 |
| 2 | 2 |
| 3 | 1 |
+----------+-------+
Now lets do normalization and store user-group data in a different table as
mysql> select * from user_to_group ;
+---------+----------+
| user_id | group_id |
+---------+----------+
| 1 | 1 |
| 1 | 2 |
| 2 | 2 |
| 3 | 1 |
| 3 | 3 |
+---------+----------+
You can easily write different queries from these tables now and here are some examples
select group_id,count(*) as tot from user_to_group group by group_id ;
+----------+-----+
| group_id | tot |
+----------+-----+
| 1 | 2 |
| 2 | 2 |
| 3 | 1 |
+----------+-----+
Joining the tables would even more easy
select
g.group_id,
g.group_name,
count(*) as tot
from user_to_group ug
join group_table g on g.group_id = ug.group_id
join user_table u on u.user_id = ug.user_id
group by g.group_id
+----------+------------+-----+
| group_id | group_name | tot |
+----------+------------+-----+
| 1 | a | 2 |
| 2 | b | 2 |
| 3 | c | 1 |
+----------+------------+-----+
SELECT group_name, COUNT(*) FROM user_table u, group_table g WHERE u.user_group_id LIKE %g.group_id% GROUP BY g.group_name;
this should work and give you a list of all groups and how many users are in them.
I will recommend you to create a third table which holds the information about which users are in which groups.
CREATE TABLE users_in_groups
(
user_id INT
, group_id INT
);
Then you can join like this:
SELECT
gt.group_id
, count(ut.user_id)
FROM
user_table AS ut
, INNER JOIN users_in_groups AS uig ON uig.user_id = ut.user_id
, INNER JOIN group_table AS gt ON gt.group_id = uig.group_id
GROUP BY
gt.group_id
;
To use the table you have now will you have to do something like this (in mysql):
SELECT
gt.group_id
, count(ut.user_id)
FROM
user_table AS ut
, INNER JOIN group_table AS gt ON LOCATE(gt.group_id, ut.user_group_id) > 0
GROUP BY
gt.group_id
Remember, when using group by, always locate what makes your group unique!
This is not an answer to your specific question but rather an alternative data structure proposal that might be better.
Introduce a new table members that looks like
# members
user_id | group_id
1 | 1
1 | 2
2 | 2
3 | 1
3 | 3
Then you could SELECT group_id, count(*) FROM members GROUP BY group_id
+----------+----------+
| group_id | count(*) |
+----------+----------+
| 1 | 2 |
| 2 | 2 |
| 3 | 1 |
+----------+----------+
This structure might also make it easier for you to manage your memberships. user_id + group_id should be unique. And if supported let them be foreign keys.
I cannot seem to get an GROUP_CONCAT query to work.
I have this tables, which I joined:
stud
id | stud_name |
-----------------
1 | Class1 |
2 | Class2 |
note
id | stud_id | mat_id | Note |
------------------------------------------------
1 | 1 | 1 | 10 |
2 | 1 | 2 | 9 |
3 | 1 | 1 | 10 |
mat
id | mat_name |
----------------
1 | Porc |
2 | Vaca |
Here is what I did to join them.
SELECT
`stud`.`id`
, `mat`.`mat_name`
, `note`.`note`
FROM
`stud`
LEFT JOIN
`note`
ON
(`stud`.`id` = `note`.`id_stud`)
LEFT JOIN
`mat`
ON
(`note`.`id_mate` = `mat`.`id`)
Here is what I want them to look.
mat.id | mat_name | Note |
-----------------------------
1 | Porc | 10,10 |
2 | Vaca | 9 |
Here is how they look.
mat.id | mat_name | Note |
-----------------------------
1 | Porc | 10 |
2 | Vaca | 9 |
1 | Port | 10 |
I tried doing this.
SELECT
`mat`.`mat_name`,
GROUP_CONCAT(`note`.`note`) AS `note`.`note`,
FROM ( "Here is what I did to join them." )attr_groups
GROUP BY `mat`.`mat_name`;
ORDER BY `mat`.`mat_name`;
Any ideas?
EDIT: If I add group by or ORDER by, no results are found. If I don't add them, the query works but its not concatenating them.
SELECT mat.id,
mat.mat_name,
GROUP_CONCAT(note.note) as note
FROM mat
LEFT JOIN note ON mat.id = note.mat_id
LEFT JOIN stud ON note.stud_id = stud.id
GROUP BY mat.id, mat.mat_name
ORDER BY mat.mat_name
SQLFiddle demo
You have error in group by.
GROUP BY `mat`.`mat_name`;
------------------------^^^---
remove ; from query
SELECT
`stud`.`id`
, `mat`.`mat_name`
, GROUP_CONCAT(`note`.`note`) AS Note
FROM
`stud`
LEFT JOIN
`note`
ON
(`stud`.`id` = `note`.`id_stud`)
LEFT JOIN
`mat`
ON
(`note`.`id_mate` = `mat`.`id`)
GROUP BY
`stud`.mat_id
ORDER BY
`mat`.`mat_name`
Try this:
SELECT
m.id,
m.mat_name,
GROUP_CONCAT(n.Note) as grades
FROM
mat m
LEFT JOIN note n
ON n.mat_id = m.id
GROUP BY
m.id