SQL and HQL retrieve data from two tables - mysql

I've two tables in Mysql.
message -> msg_id(pk) and message(varchar)
track_record -> tr_id(pk), msg_id (foreign key), object_id (to whom the message is sent), profile_id(who sent the message)
Now i want to create a single query which gives me the messages and the sender profile id given the object_id.
E.g say i have the object_id 1.
Now i want to see all the message sent to the user with id 1.
Edited the answer to add my query which i tried
SELECT m.message, u.profile_profile_id FROm `message` as m, `user_track_record` as u
WHERE msg_id IN
(SELECT message_msg_id FROM user_track_record WHERE object_profile_id = 1)
and u.profile_profile_id IN
(SELECT profile_profile_id from `user_track_record` WHERE object_profile_id = 1)
Want to do this in both SQL and HQL.
Any help appreciated. Thanks

Your SQL query is much too complex.
Start with simple things:
Select all the track_records sent to user 1:
select tr.* from track_record tr where tr.object_id = 1
Now you would like the message linked to the track record. This is done using a join:
select tr.*, m.* from track_record tr
inner join message m on m.msg_id = tr.msg_id
where tr.object_id = 1
Now you would like only the ID of the sender, and the body of the message:
select tr.profile_id, m.message
from track_record tr
inner join message m on m.msg_id = tr.msg_id
where tr.object_id = 1
In HQL, the query is almost identical. You have a Message entity and a TrackRecord entity. TrackRecord has a ManyToOne association with Message. It also has a ManyToOne association with the sender and the receiver
select tr.sender.id, m.message
from TrackRecord tr
inner join tr.message m
where tr.receiver.id = 1

Related

better way of doing this SELECT in MySQL

Best way to do this SELECT?
I've got this tables:
t_department
id
name
t_users
id
name
type
*type can be:
1 SuperUser
2 normalUser
t_department_superuser
(A department can have many superUsers)
-idSuperUser
-idDepartment
t_superuser_normaluser
(A superUser can have many normalusers)
-idSuperUser
-idNormalUser
and finally
t_actions
-id (autonumeric)
-idUser (this can be an id of superUser or normalUser)
-action
Given a department name, for example "mainDepartment"
I need to get all records from t_actions of all normalusers and all superusers of that department
I have this, it works, but I am not an SQL expert (I am using MySQL) and I think it is not the best way to do the select, and t_actions is going to have loads of rows:
SELECT id,idUser,action
FROM t_actions
WHERE (idUser IN (
SELECT DISTINCT t_department_superuser.idSuperUser FROM t_department
RIGHT JOIN t_department_superuser ON t_department_superuser.idDepartment = t_department.id
LEFT JOIN t_superuser_normaluser ON t_superuser_normaluser.idSuperUser = t_department_superuser.idSuperUser
WHERE name='mainDepartment'
UNION ALL
SELECT DISTINCT t_superuser_normaluser.idNormalUser
FROM t_department
RIGHT JOIN t_department_superuser ON t_department_superuser.idDepartment = t_department.id
LEFT JOIN t_superuser_normaluser ON t_superuser_normaluser.idSuperUser = t_department_superuser.idSuperUser
WHERE name='mainDepartment')
ORDER BY id;
Any suggestions to make this better? thank you!!
because you are using left and right joins there will be null records, which is why you need the UNION... you can cut out the UNION with a simple null check
SELECT id, idUser, action
FROM t_actions
WHERE idUser IN
( SELECT DISTINCT COALESCE(tsn.idNormalUser, tds.idSuperUser)
FROM t_department td
RIGHT JOIN t_department_superuser tds ON tds.idDepartment = td.id
LEFT JOIN t_superuser_normaluser tsn ON tsn.idSuperUser = tds.idSuperUser
WHERE td.name='mainDepartment'
)
ORDER BY id;
note i also added alias's to your table names so its easer to write out and read the columns you are trying to select and join on.
EDIT
with the data the only possible way to do it with this table design is like this
SELECT id, idUser, action
FROM t_actions
WHERE idUser IN
((SELECT tds.idSuperUser
FROM t_department td
JOIN t_department_superusers tds ON tds.idDepartment = td.id
WHERE td.name='MAIN')
UNION
(SELECT tsn.idNormalUser
FROM t_department td
JOIN t_department_superusers tds ON tds.idDepartment = td.id
JOIN t_superuser_normaluser tsn ON tsn.idSuperUser = tds.idSuperUser
WHERE td.name='MAIN')
)
ORDER BY id;

Trying to building optimised Query for Group and Subgroup for a user

i am trying to write the Query for three things .My table structure is like that
You can see Schema at http://sqlfiddle.com/#!2/56c2d/1
I am trying to write the query in MYSQL
user:- table
user_id
user_fname
This is User tabke which will save User Information
group:- "group" and "subgroup" is maintain in same table using column "group_parent_group_id"
group_id
group_title
group_parent_group_id(INT)
This is group table which will save Group and Subgroups
user_group: table
user_group_id
user_group_user_id
user_group_group_id
This ill store both User and Group relation using their Id
I am trying to write the Query for three things. Fetching Users Groups, Subgroups
1) Query to fetch list of All Groups for User Register. Query is gelow and is giving error
Query:
select user.id, user.user_fname, group.group_id, group.group_title
from `user`
inner join user_group on user_group.user_group_user_id = user.user_id
inner join group on group.group_id = user_group.user_group_group_id
where user_group.user_group_user_id = 1 and user_group.group_parent_group_id = 0
2) I am Looking the query to fetch all subgroups(For Whom user is already Register) for Group Id 1,2 or 1
3) I am Looking the query to fetch all subgroups(For Whom user is Not Register yet) for Group Id 1,2 or 1. Ideal is for giving him randomly suggest a subgroup to add
Please Help. I am a newbie in DB :(
Your query is probably failing as you have a table called group, which is a reserved word. You can use back tics to delimit the name to get away with this (as follows) but it would be a better idea to change the table name.
SELECT user.id, user.user_fname, `group`.group_id, `group`.group_title
FROM `user`
INNER JOIN user_group ON user_group.user_group_user_id = user.user_id
INNER JOIN `group` ON `group`.group_id = user_group.user_group_group_id
WHERE user_group.user_group_user_id = 1
AND user_group.group_parent_group_id = 0
EDIT updated for queries I think the OP requires.
First query will get a list of all the groups (ones that have no parent group id) that a user (in this case id 28) is a member of
SELECT y2m_user.user_id, y2m_user.user_first_name, y2m_group.group_id, y2m_group.group_title
FROM y2m_user
INNER JOIN y2m_user_group ON y2m_user_group.user_group_user_id = y2m_user.user_id
INNER JOIN y2m_group ON y2m_group.group_id = y2m_user_group.user_group_group_id
WHERE y2m_user.user_id = 28
AND y2m_group.group_parent_group_id = 0
This query will get a list of all the sub groups (ones where the parent group id is greater than 0) that a user (in this case id 28) is a member of
SELECT y2m_user.user_id, y2m_user.user_first_name, y2m_group.group_id, y2m_group.group_title
FROM y2m_user
INNER JOIN y2m_user_group ON y2m_user_group.user_group_user_id = y2m_user.user_id
INNER JOIN y2m_group ON y2m_group.group_id = y2m_user_group.user_group_group_id
WHERE y2m_user.user_id = 28
AND y2m_group.group_parent_group_id > 0
This query will get a list of all the sub groups (ones where the parent group id is greater than 0) that a user (in this case id 28) is NOT a member of
SELECT y2m_user.user_id, y2m_user.user_first_name, y2m_group.group_id, y2m_group.group_title
FROM y2m_user
CROSS JOIN y2m_group
LEFT OUTER JOIN y2m_user_group ON y2m_user_group.user_group_user_id = y2m_user.user_id AND y2m_group.group_id = y2m_user_group.user_group_group_id
WHERE y2m_user.user_id = 28
AND y2m_group.group_parent_group_id > 0
AND y2m_user_group.user_group_id IS NULL
Please excuse any typos as not tested (with your test data there are no sub groups).

SQL join multiple times?

I am making a user status list of the following format "A like B's XXX". A and B are both registered users and have firstname and lastname and user id. How to join the status table with the user table twice to get the names of the two users? Thank you.
SELECT "SQACTION"."TIMECREATED",
"SQWORDLIST".*,
"SUBJECT"."FIRSTNAME" subject_fn,
"SUBJECT"."LASTNAME" subject_ln,
author.firstname author_fn,
author.lastname author_ln
FROM "SQACTION"
INNER JOIN "SQWORDLIST"
ON SQACTION.ACTION = SQWORDLIST.GUID
INNER JOIN "SQUSER" SUBJECT
ON SQACTION.SUBJECT = SUBJECT.GUID
LEFT JOIN SQDOCUMENT
ON SQACTION.ENTITY = SQDOCUMENT.GUID
LEFT JOIN SQUSER AUTHOR
ON SQDOCUMENT.AUTHORID = AUTHOR.GUID
WHERE (SUBJECT.GUID = 'B4D3BF632C0C4DB3AB01C8B284069D8F')
OR (SUBJECT.GUID IN ('67882AF3FA3C4254AF9A12CA0B0AB6E4',
'6A4B52FE233444838AACFE2AFFE4D38F',
'8CA3FB9061FF4710B51F1E398D3D1917'))
ORDER BY "TIMECREATED" DESC
This is what I have tried. Thank you.
You need to include the table name twice in the FROM clause, and use an alias so you can specify which fields from each instance of the table are used in the ON statement. You didn't provide enough details in your question to give an exact example, so here is something more general.
UserTable, with ID & Name
RegTable, with UserID, and SponsorID
select ut1.name as [User],
ut2.name as [Sponsor]
from UserTable ut1
inner join RegTable rt on ut1.id = rt.userid
inner join UserTable ut2 on rt.sponsorid = ut2.id
do you mean something like, status have two field links to user table?
select user_a.first_name as user_a_first_name, user_b.first_name as user_b_first_name, status.status_name
from status
left join users as user_a on user_a.id = status.user_from_id
left join users as user_b on user_b.id = status.user_to_id

selecting rows from table which have distinct values for a column

In my thread based messaging system, the table schema is
> messages table
id(int auto incr primary key)
body(varchar)
time(datetime)
>message_reference table
id(int auto incr primary key)
message_id(forgain key from message table)
sender
receiver
Here, I want to select the first message id which is sent to a new receiver and sender is the user who is logged in.
Doing this with multiple queries and some code is obviously possible but can it be done with a single query for performance issues??
You can try
EDIT:
If the id is auto increment, then the id will also increase with time and you can use:
SELECT message_reference.message_id, message_reference.receiver, messages.body
FROM message_reference, messages
WHERE message_reference.message_id IN (SELECT MIN(message_reference.message_id)
FROM message_reference
GROUP BY message_reference.receiver)
AND message_reference.message_id = messages.id AND message_reference.sender = <sender>
Here's my best guess as to what you want, but it would be easier if you gave known inputs, example data, and expected output.
SELECT
MR2.message_id
FROM (
SELECT
MR.sender,
MR.receiver,
M.MIN(`time`) AS min_time
FROM
Message_References MR -- Either use plural names (my personal preference) or singular, but don't mix them
INNER JOIN Messages M ON
M.id = MR.message_id
WHERE
MR.sender = <sender>
GROUP BY
MR.received) SQ
INNER JOIN Message_References MR2 ON
MR2.sender = SQ.sender AND
MR2.receiver = SQ.receiver AND
MR2.`time` = SQ.min_time
select mr.message_id from
message_reference as mr inner join
(select mr1.reciever max(m1.time) as time from messages as m1
inner join message_reference as mr1 on mr1.message_id = m1.id
group by mr1.reciever) as last
on mr.reciever = last.reciever and mr.time = last.time
join message reference with "maxtime per reciever" table on reciever and time
Well I got the answer, Just a group by query worked the way I wanted. I used query
SELECT SENDER,
RECEIVER,
BODY,
TIME,
MESSAGE_ID
FROM MESSAGE_REF JOIN MESSAGE
ON MESSAGE.ID=MESSAGE_REF.MESSAGE_ID
ORDER BY 'TIME' GROUP BY RECEIVER`
Thanks everyone for the help.

Need some support writing a MySQL-Query

I'm writing a basic message-script in PHP/MySQL but I'm stuck at a database query right now. I'll appreciate any hints or assistance (:
I'm using two tables, since a message can be sent to several users:
messages:
id | sender_id | subject | ...
message_receivers:
message_id | receiver_id | ...
What I want to do now is display a message to the user that he selects. But I want to show the whole message history the user had in that conversation (jumping in browser to the one he selected). Doing this with a join is quite simple:
SELECT * FROM messages
JOIN message_receivers
ON messages.id = message_receivers.message_id
WHERE sender_id = x
AND receiver_id = y
But now I'm missing the information of other receivers of a message! And I have no clue how to get this information. Any ideas for that? (:
Join the message_receivers table one more time to retrieve the other recipients of the message:
SELECT
m.id, m.sender_id, m.subject,
r.receiver_id AS recipient,
c.receiver_id AS carboncopy
FROM messages AS m
INNER JOIN message_receivers AS r
ON m.id = r.message_id
LEFT OUTER JOIN message_receivers AS c
ON r.message_id = c.message_id AND r.receiver_id != c.receiver_id
WHERE m.sender_id = x AND r.receiver_id = y
The recipient that your are interested in will be in column recipient (in every result record). Other recipients will be in column carboncopy (one per result record). If carboncopy is NULL, then the message had only a single receiver.
If you want to see all the receivers of a message then remove the second part of the were clause:
AND receiver_id = y
at the same time you will want to specify the message_id because this will be to confusing to the user on the front end
AND message_id = z
You're missing information about other receivers of the message because of the clasue:
AND
receiver_id = y
This restricts the result set to just receiver y. Remove the clause, and you'll get them all. However you'll probably get every message sent where sender_id = x as well, so you'll need to limit the query by specifying a message_id.
So your final query should look something like this:
SELECT
*
FROM
messages
JOIN message_receivers ON messages.id = message_receivers.message_id
WHERE
sender_id = x
AND
message_id = y
you don't need to restrict your result to receiver_id = y, do you?
Also you might write the statement in a different way and easily return receivers ids:
SELECT m.*, r.receiver_id
FROM messages m, message_receivers r
WHERE m.id = r.message_id
AND m.sender_id = x