Add up column using while not breaking other code - php

My connect to my database works fine so I will include just the code. What I am trying to do is create a sum of the total hours spent on a specific project. The code I have right now displays the comments all the comments from the last day the project was updated:
$query = "SELECT id, date,(select username from users where id = u.user_id) as user, (select description from requests where id = u.request_id) as request, notes, hours from updates u where u.request_id=$rid and date(date) = (select max(date(date)) from updates where request_id = $rid) order by (select description from requests where id = u.request_id) asc";
This is how it is displayed on the web page:
Click to see image of what is displayed on web page
The "test" code that I have that will add the total hours:
$query = "SELECT id, date,(select username from users where id = u.user_id) as user, (select description from requests where id = u.request_id) as request, notes, SUM(hours) as clienthours, hours from updates u where u.request_id=$rid and date(date) = (select max(date(date)) from updates where request_id = $rid) order by (select description from requests where id = u.request_id) asc
This is how it is display on the web page. Notice that all the other comments are gone except the first one of the day.
Click to see image of what is display on web page
I tried adjusting the order of the query but it will send me errors and break the code. I haven't been able to find a solution and would appreciate any help I can get. I am not very advanced when it comes to PHP so my methods are odd and I am building off of someone else code. Any advice will help!
Thank you.

I'd suggest that the main issue with your second script is that you are trying to SUM a column which is returning one row, in SQL you can only return a SUM() when it is the only column in your SELECT.
The below should get around this and also will be more efficient for you by using joins (I've made the assumption that updates.request_id is the unique primary key)
SELECT up.id, up.date, us.username, description, notes,
(SELECT SUM(Hours) FROM updates z WHERE z.request_id = up.request_id)
FROM updates up
INNER JOIN requests r ON u.request_id = r.id
INNER JOIN users us ON up.user_id = us.id
WHERE up.request_id = $rid AND
up.date = (SELECT MAX(date) FROM updates WHERE request_id = $rid)
ORDER BY r.description ASC;

Related

One record 27 times

I have a big problem with MySQL. I want to write script like facebook newsfeed.
My query return me 27 the same records. I don't know why.
How it works?
Script displaying posts written by me, my friends or my profile.
My tables:
users:
id, firstname, lastname
friends:
friend1, friend2, status, date
wall:
update_id, author, to_profile, content, date, photos
My query:
SELECT wall.update_id, wall.author, wall.to_profile, wall.content, wall.date, wall.photos, users.*, friends.sender_id, friends.friend_id, friends.status
FROM
wall
INNER JOIN friends ON
wall.author = friends.sender1
AND friends.friend2 = '".$_SESSION['id']."'
AND friends.status = '1' OR wall.author = '".$_SESSION['id']."'
OR wall.to_profile = '".$_SESSION['id']."'
INNER JOIN users ON users.id = wall.author
ORDER BY wall.date DESC
I also want to display post written by pages which I liked.
I created tables:
pages:
page_id, page_name
page_likes:
page_id, user_id, date
and *pages_wall:**
like_id, page_id, user_id, date
How to connect this to my query? And (the most important) how to repair my query?
Thanks in advance,
Matthew
That's a lot of joining going on. Try using your JOINs just to connect the tables, and then use WHERE to cut down the results. Because as it stands, those ORs aren't working like you probably think they are, they need some () around them.
I think you need some structural changes to this database for it to work well in the future. I'd add an ID field to friends, even if just on the admin side, you're going to want to manage those records.
Also, you shouldn't be querying user.* in this query. It seems like you want to pull out every user setting... for every single wall post. This will get rid of "INNER JOIN users ON users.id = wall.author " at the end which will help. Get that information in it's on query prior to calling this wall display.
SELECT *
FROM users
WHERE users.id = wall.author

PHP, MySQL: How to get the user's first and last name

I got stucked with this query in the past couple of hours, and I badly need someone to help me figure it out. I'm try to finish my private message system, but I lost myself in the database tables. I've created three tables for the system, and they are as follows:
CONVERSATION(**conversation_id**, subject)
CONVERSATION_MEMBER(**conversation_id**, **user_id**, conversation_last_view, conversation_deleted)
CONVERSATION_MESSAGE(**message_id**, conversation_id, user_id, message_date, message_text)
Ok, so in my function to get all conversations of a specific user, I'm fetching the subject, the date, and at last I want to show the user who is he/she talking to. I wrote the following query:
SELECT
c.conversation_id,
c.conversation_subject,
MAX(cmes.message_date) AS conversation_last_reply,
FROM conversation c, conversation_member cmem, conversation_message cmes
WHERE c.conversation_id = cmes.conversation_id
AND c.conversation_id = cmem.conversation_id
AND cmem.user_id = {$_SESSION['user_id']}
AND cmem.conversation_deleted = 0
GROUP BY c.conversation_id
ORDER BY conversation_last_reply DESC
And, at last I'm tryin to get the user's first and last name (the other user in the conversation), but I lost myself on how to do that. I've tried to create another function that will get the conversation id, while looping through the results of the first query, and return the user's first and last name, but it didn't work out.
Btw, for the users I have another table... I guess I don't have to tell you. Ok, thank you.
$sql = "SELECT (user.forename, user.surname, other_fields...)
FROM conversation
INNER JOIN conversation_member
ON conversation.conversation_id = conversation_member.conversation_id
INNER JOIN conversation_message
ON conversation.conversation_id = conversation_message.conversation_id
INNER JOIN users_table /* replace this with the name of your user table */ AS user
ON user.user_id = conversation_member.user_id
WHERE user.user_id = :userid
AND conversation_member.conversation_deleted = 0
GROUP BY conversation.conversation_id;"
$query = $db->prepare($sql);
$query->bindParam(':userid', $userid, PDO::PARAM_INT);
$query->execute();
$results = $query->fetchAll();
$user = $results[0]["user"]; //stores array of user fields (forename, surname, etc)
SELECT
c.conversation_id,
c.conversation_subject,
user.firstname,
user.lastname,
MAX(cmes.message_date) AS conversation_last_reply,
FROM conversation c, conversation_member cmem, conversation_message cmes, user_tablename user
WHERE c.conversation_id = cmes.conversation_id
AND c.conversation_id = cmem.conversation_id
AND cmem.user_id = {$_SESSION['user_id']}
AND cmem.conversation_deleted = 0
AND user.user_id_column = whatever.you_used_as_foriegn_key
GROUP BY c.conversation_id
ORDER BY conversation_last_reply DESC
Assuming the columns names are like that
You need to join with the "conversation_member" table again, this time, selecting the other user's id where the same conversation_id and message_id applies:
SELECT
c.conversation_id,
c.conversation_subject,
MAX(cmes.message_date) AS conversation_last_reply,
cmem2.user_id AS other_user_id
CONCAT(usr_tbl.firstname, ' ', usr_tbl.lastname) AS other_user_name
FROM conversation c
JOIN conversation_member cmem
JOIN conversation_message cmes
JOIN conversation_member cmem2
JOIN users_table usr_tbl
ON c.conversation_id = cmes.conversation_id
AND c.conversation_id = cmem.conversation_id
AND cmem.user_id = {$_SESSION['user_id']}
AND cmem.conversation_deleted = 0
AND c.conversation_id = cmem2.conversation_id
AND cmem2.user_id = {$_SESSION['other_user_id']}
AND cmem2.conversation_deleted = 0
GROUP BY c.conversation_id
ORDER BY conversation_last_reply DESC
I don't see why you're having trouble getting the user's first and last name if you were able to construct the rest of that query by yourself?
Try something along the lines of, :
SELECT cmem.user_id, u.first_name, u.last_name, c.conversation_id, c.conversation_subject, MAX(cmes.message_date) AS conversation_last_reply
FROM conversation c
INNER JOIN conversation_member cmem on c.conversation_id=cmem.conversation_id
INNER JOIN conversation_message cmes on c.conversation_id=cmes.conversation_id
INNER JOIN users u on u.user_id = cmem.user_id
WHERE cmem.user_id = {$_SESSION['user_id']} AND cmem.conversation_deleted = 0
GROUP BY cmem.user_id, u.first_name, u.last_name, c.conversation_id, c.conversation_subject
Now, I think you should also be reconsidering your database structure so that all these joins are not necessary. I see several problems. One, your database seems to be over-normalized. Why do you have a separate "Conversations" table that has only two fields, conversation id and subject? In any message system I've ever seen, the subject is always visible so you would always have to join the conversation table just to get the subject field. The conversation_id is in every other table anyway. Just add the subject field to the message table and eliminate the conversation table if that's all it's holding, normalization isn't always a good thing.
Second, why do you set a flag for deleted messages instead of just deleting them? I've also never seen a message system that lets me restore messages I've deleted. At the very least, if you want to retain them for whatever reason you should move them to an archive table so that the primary table you're running selects off of doesn't have to deal with the performance hit of parsing through meaningless "deleted" entries.
Lastly, what is the conversation_member table anyway? Based on my interpretation, it's supposed to represent a member of the conversation since it has a user_id. Why would the conversation delete flag be present for a single member of a conversation? If anything it should be in the conversation table. With that improvement, the only field left in it is conversation_last_view, which really no one cares about. The more important thing is conversation_last_post, which can be easily derived from the timestamp of the last message posted in the thread.
Ultimately, if you just want to see the first and last names appended to your query it's as simple as joining the users table and displaying those two entries. The SQL query I provided should get you close if it doesn't work straight out, I'm too lazy to copy your database and try it myself. However, I think you should really consider the overall design of your database as well so you don't run into needless performance issues down the road.
To answer the question of: Finding all users in a conversation, MINUS the current user:
SELECT (users.forename, users.surname)
FROM conversation_members AS members
INNER JOIN users_table AS users
ON members.user_id = users.user_id
WHERE members.conversation_id = :conversationid
AND NOT users.user_id = :userid
Where :userid is the current user and :conversationid is the conversation in question.

how to get position rank of specific row using just mysql query?

I have table Users which contains columns: id, name, points, extra_points.
How can I get position rank for specific user, when the rank is sum of points and extra_points?
For all users list rank Im using this query: "SELECT id, (points + extra_points) AS total FROM users ORDER BY total desc"; and the while loop with html ol tag (so there is position number).
But I dont know how to show the rank for a sinlge user (in user profile page)?
Any help will be great.
SELECT users1.id, (users1.points+users1.extra_points) AS total, COUNT(*)+1 AS rank
FROM users users1
INNER JOIN users users2 ON users1.points+users1.extra_points < users2.points+users2.extra_points
WHERE users1.id = $id
Well, for a single user, you'd change the select query so it looks like
"SELECT (points + extra_points) AS total FROM users WHERE id = $id LIMIT 1"
Need to specify which user as a WHERE clause. Also, since you presumably know the id already, don't need to select it, and since it's just one user, don't need the ORDER BY either. And LIMIT 1 will stop it from checking the rest of the rows once it's found it.
this isn't tested, but i hope you can understand whats my idea - simply use a subselect to count all users with more points:
SELECT
id,
(points + extra_points) AS total,
(SELECT COUNT(*) FROM users WHERE (points + extra_points)) >= (u.points + u.extra_points) AS rank
FROM
users u
WHERE
id = ?;
Here's the answer if you have a ClientID and Points column in a table called Client:
<CFQUERY DATASOURCE="YourDatasource" name="YourQueryName">
SELECT ClientID, (Pts) AS total,
(SELECT COUNT(*) FROM Client
WHERE (Pts) >= (u.Pts)) AS rank
FROM Client u
WHERE ClientID = CLIENTID_OF_YOUR_CHOICE_HERE;
</CFQUERY>

How to call specific rows from a table in MySQL ? (see the case)

The website is intended for users to enable them joining the courses and posting their updates to these courses and also receiving the course updates made by others (imagen courses as Groups in Facebook but in my website users post updates ONLY through the courses)
When the user login to the website, he is suposed to see all the updates in the courses he already is joined in.
I have many tables in MySQL :
'updates' which have these attributes (id, account_id,course_id,datetime,content) noticing that course and account ID's are foreign keys..
'courses' which have these attributes (id,name,..)
'accounts' which have these attributes (id,full_name,...)
'accounts_courses_relationship' (account_id,course_id) , to map the relations between users and courses.
I have tried many times but the only thing I get is to show all the updates for all courses without excluding the updates from the courses that user isn't a member of, as follow:
$sql = "SELECT DISTINCT datetime, content
FROM updates
WHERE account_id != {$account_id}
ORDER BY datetime DESC
LIMIT 10";
So, How to exclude the updates from these courses?
Note: don't forget that all mappings between users and courses are registered in a table shown above..
Well i might be not seeing your problem it but how about
SELECT ... FROM updates where account_id = {$account_id}
Would't this select all updates for the current user and therefore all the updates the user is interested in?
something like this should work
select *
from updates u
join accounts_courses_relationship r on u.courseid = r.courseid
where r.account_id = {$account_id}
You have to inner join the updates and courses and accounts and accounts_courses tables.
select acr.accountid, acr.courseid, courses.name, accounts.fullname, updates.datetime, updates.content
from accounts_courses_relationship acr
inner join courses on acr.courseid=courses.courseid
inner join accounts on acr.accountid = accounts.accountid
inner join updates on updates.accountid= accounts.accountid and updates.courseid=courses.courseid
where accountid = {?}
order by updates.datetime desc
If you're interested in seeing updates to courses from other users (not you) and you're a registered user of those courses:
SELECT DISTINCT datetime, content
FROM updates
WHERE account_id != {$account_id}
and course_id in (select acr.course_id from accounts_courses_relationship acr where acr.account_id = updates.account_id)
ORDER BY datetime DESC
LIMIT 10

help me in this query

i am trying to develop a site where users can become friends of each other and can see their posts after the date the became friends........i have already posted this question about 5-7 days but could not find any solution........!!
so...
i have two tables..........
posts and friends
and my query is
$sql = mysql_query("
SELECT *
FROM posts p
JOIN friends f
ON p.currentuserid = f.friendid
AND p.time >= f.friend_since
OR s.currentuserid=$myid
WHERE f.myid=$thisid
ORDER BY p.postid DESC LIMIT 20");
where $myid is currentuserid and p.currentuserid is the name of cell in poss table and friendid is in friends table.
this query is working all the way right but problem is that in this query if current user post any thing it displays two times i.e
my new post
mynew post
but in database it is single entry.....!! but current user can see their friends posts for single time
how can i solve this problem
this query is working all the way right but problem is that in this query if current user post any thing it displays two times
Use:
SELECT DISTINCT *
FROM posts p
JOIN friends f ON p.currentuserid = f.friendid
AND p.time >= f.friend_since
OR s.currentuserid=$myid
WHERE f.myid=$thisid
ORDER BY p.postid DESC
LIMIT 20
I added the DISTINCT keyword in order to remove duplicates. Usually I'd use a GROUP BY instead, but you didn't supply the columns.

Categories