I've been playing with LEFT JOINs and I'm wondering if it's possible to get the SUM of all the ratings so far from all users in the below query. The below get's me the information on if the logged in user has rated or not, but i want to show total ratings from other users also.
$query = mysql_query("
SELECT com.comment, com.comment_id, r.rate_up, r.rate_down
FROM comments com
LEFT JOIN ratings r
ON com.comment_id = r.comment_id
AND r.user_id = '" . $user_id_var . "'
WHERE page_id = '" . $category_id_var. "'");
I've tried the following but i only get one comment/row returned for some reason.
$query = mysql_query("
SELECT com.comment, com.comment_id,
r.rate_up, r.rate_down
SUM(r.rate_up) AS total_up_ratings,
SUM(r.rate_down) AS total_down_ratings,
FROM comments com
LEFT JOIN ratings r
ON com.comment_id = r.comment_id
AND r.user_id = '" . $user_id_var . "'
WHERE page_id = '" . $category_id_var. "'");
Any help appreciated. Do i need a different kind of JOIN?
Have you tried using GROUP BY page_id on the end of your SQL?
You could do it something like this:
SELECT
com.comment,
com.comment_id,
Total.total_down_ratings,
Total.total_up_ratings
FROM comments com
LEFT JOIN
(
SELECT
SUM(r.rate_up) AS total_up_ratings,
SUM(r.rate_down) AS total_down_ratings,
r.comment_id
FROM
ratings r
GROUP BY
r.comment_id
) AS Total
ON com.comment_id = Total.comment_id
AND r.user_id = '" . $user_id_var . "'
WHERE page_id = '" . $category_id_var. "'"
If you use an aggregation function in SQL (like SUM()) you will need a corresponding GROUP BY clause.
In your case the most likely one would be com.comment_id; this will give you the sum of all ratings per comment_id:
I don't know if you are duplicating comment rows for purpose but if not you can try write subselect for ratings like this:
select comment_id, user_id, sum(rate_up) as sum_rate_up,
sum(rate_down) as sum_rate_down from ratings
group_by comment_id, user_id;
and then include it in your join query:
select com.comment, com.comment_id, r.user_id, r.sum_rate_up,
r.sum_rate_down from comments com
left join (select comment_id, user_id, sum(rate_up) as sum_rate_up,
sum(rate_down) as sum_rate_down from ratings
group_by comment_id, user_id) as r
on com.comment_id = r.comment_id where page_id = '".$category_id_var."'
Related
Here's my current query:
$q = "SELECT u.uid,CONCAT_WS(' ', u.first_name, u.last_name) name, CASE WHEN t.name IS NULL THEN 0 ELSE t.name END AS teamname ";
$q .= "FROM {$users} ";
$q .= "LEFT JOIN {$schedule} ON u.uid = s.uid ";
$q .= "LEFT JOIN {$products} ON p.admitting_id = u.uid ";
$q .= "LEFT JOIN {$teams} ON t.id = s.team ";
$q .= "WHERE (u.uid = {$current_user_id} AND u.roles = 'hoa') OR ";
$q .= "(p.id={$pid} AND p.admitting_id != 0) OR ";
$q .= "(t.admitting = 1 AND s.inactive != 1 AND s.role = 'hoa' AND (s.date = '{$today}' OR (s.date = '{$yesterday}' AND t.overnight = 1))) ";
$q .= "ORDER BY u.last_name,u.first_name,t.name";
What I need to get is:
Current User, if Current User has role hoa
User where uid matches admitting_id from products table
All users with role hoa who are scheduled today or were scheduled yesterday on an overnight shift. With those scheduled users, I need the names of the team they were/are scheduled with. Duplicate uids is good because I need all the different team names if they were scheduled on multiple teams.
What I don't need to get is:
Team name for options 1 and 2 above.
What I'm getting is:
Everything perfect for #3 above.
All possible team names for #1 and #2 above, whereas I want the team names to be 0 if they're not on the schedule.
I could split this up into three queries but that's not preferable.
Sometimes formatting the query out a bit helps visualise. It doesn't need to become three queries, I agree.
Can you provide some sample schema and data, ideally both in the question description and on something like sqlfiddle for us to play with?
It's hard to visualise your structure and data, but I'm speculating the issue is every record in users table is joining to schedule with the on clause you've used.
You could move the logic of condition 3 into the on clause (it's a left join, so nothing else will break) or duplicate it in the CASE statement in the SELECT:
$q = <<<SQL
SELECT
u.uid,
CONCAT_WS(' ', u.first_name, u.last_name) name,
IF(
WHEN t.name IS NULL THEN
0
ELSE
t.name
END AS teamname
FROM {$users} AS u
LEFT JOIN {$schedule} AS s ON (u.uid = s.uid)
LEFT JOIN {$products} AS p ON (p.admitting_id = u.uid)
LEFT JOIN {$teams} AS t ON
(
t.id = s.team AND
t.admitting = 1 AND
s.inactive != 1 AND
s.role = 'hoa' AND
(
s.date = '{$today}'
OR
(
s.date = '{$yesterday}' AND
t.overnight = 1
)
)
)
WHERE
( -- 1: Current User, if Current User has role hoa
u.uid = {$current_user_id} AND
u.roles = 'hoa'
)
OR
( -- 2: User where uid matches admitting_id from products table
p.id={$pid} AND
p.admitting_id != 0
)
OR
t.name IS NOT NULL
ORDER BY
u.last_name,
u.first_name,
t.name
SQL;
I'm absolutely not certain that'll fix your problem without something real to play with... Happy to continue looking if you can provide a working example sandpit.
I have a table with both, Products and Sevices. And I store the products brands, product names and services names on separate tables.
I get the list of Services with this Query:
SELECT maeinvs.idInv, CONCAT(services.Service, " ", maeinvs.Detail) AS Name
FROM maeinvs
INNER JOIN services
ON services.idService = maeinvs.idService
And the list of Products with this one:
SELECT maeinvs.idInv, CONCAT(brands.Brand, " ", products.Product, " ", maeinvs.Detail) AS Name
FROM maeinvs
INNER JOIN products
ON products.idProduct = maeinvs.idProduct
INNER JOIN brands
ON brands.idBrand = maeinvs.idBrand
I need to get a Query like this, but instead of the idInv field I need the actual Name of the Product or Service. Any ideas?
SELECT idInv, Desc, Qnty, Price
FROM invoicedetails
WHERE idInvoice = $id
Thanks.
SELECT maeinvs.idInv, CONCAT(services.Service, " ", maeinvs.Detail) AS Name,
"" AS Desc, 0 AS Qnty, 0 AS Price
FROM maeinvs
INNER JOIN services
ON services.idService = maeinvs.idService
UNION
SELECT maeinvs.idInv, CONCAT(brands.Brand, " ", products.Product, " ", maeinvs.Detail) AS Name,
"" AS Desc, 0 AS Qnty, 0 AS Price
FROM maeinvs
INNER JOIN products
ON products.idProduct = maeinvs.idProduct
INNER JOIN brands
ON brands.idBrand = maeinvs.idBrand
UNION
SELECT idInv,
"" AS Name,
Desc, Qnty, Price
FROM invoicedetails
WHERE idInvoice = $id
I've written what I've changed on next line
As the columns match each other, UNION will work.
I still don't know how to do it on a single query (I just know the basics; an Alias?) but solved it doing a VIEW and then a JOIN with my invoicedetails table.
VIEW:
SELECT maeinvs.idInv, CONCAT(services.Service, " ", maeinvs.Detail) AS Name
FROM maeinvs
INNER JOIN services
ON services.idService = maeinvs.idService
UNION
SELECT maeinvs.idInv, CONCAT(brands.Brand, " ", products.Product, " ", maeinvs.Detail) AS Name
FROM maeinvs
INNER JOIN products
ON products.idProduct = maeinvs.idProduct
INNER JOIN brands
ON brands.idBrand = maeinvs.idBrand
QUERY:
SELECT viewnames.Name, invoicedetails.Desc, invoicedetails.Qnty, invoicedetails.Price
FROM invoicedetails
INNER JOIN viewnames ON viewnames.idInv = invoicedetails.idInv
WHERE invoicedetails = $id
How can I implement search function:
where sub_menu_name like '%".$kws."%'
into my working one:
SELECT DISTINCT p.id, p.sub_menu_id, p.sub_menu_name, m.image_id, i.file_url, m.default_menu_id, p.restaurant_id, p.status, p.sub_menu_price
FROM sub_sub_menu AS p
INNER JOIN menu AS m ON m.default_menu_id = p.sub_menu_id
OR m.id = p.sub_menu_id
INNER JOIN icon AS i ON i.id = m.image_id
WHERE p.restaurant_id = '" . (int) $_SESSION['uid'] . "' "
Thanks for any help!
SELECT DISTINCT p.id, p.sub_menu_id, p.sub_menu_name, m.image_id, i.file_url, m.default_menu_id, p.restaurant_id, p.status, p.sub_menu_price
FROM sub_sub_menu AS p
INNER JOIN menu AS m ON m.default_menu_id = p.sub_menu_id
OR m.id = p.sub_menu_id
INNER JOIN icon AS i ON i.id = m.image_id
WHERE p.restaurant_id = '" . (int) $_SESSION['uid'] . "'
AND sub_menu_name LIKE '%".$kws."%'
I think this is what you want.
But I wonder why you have ". and ." before and after $kws. It's meant for concatenation so it won't work in SQL. If you want to check for $kws IN a value, the % % are enough.
How could I fetch a specific record only and if a condition is met?
I have the code as
"SELECT a.id, a.text, a.uid, a.time
FROM story a INNER JOIN friends b
ON ((a.uid = '" . $uid . "') OR
(b.uid = '" . $uid . "' AND accepted='1') OR
(b.fid = '" . $uid . "' AND accepted='1'))
ORDER BY a.time DESC
LIMIT 3";
It works fine except that when the friends table is empty, it will not show the story records.
what i want to achieve is
if the uid in table story is equal to logged in uid (user), then show the text from table story (meaning it is his own story)
if the uid in table story is equal to uid in table friends and its friendship is accepted OR if the uid in table story is equal to fid in table friends and its friendship is accepted then show the text in table story (meaning the story is from a friend and its shown only if friendship is accepted)
if there is no friendships at all, just show own stories from table story and omit others
I think you are not using proper join format. It should be as :
SELECT field_name
FROM table1 t1
INNER JOIN table2 t2
ON t1.id = t2.some_id
WHERE..
You can check the basics here.
In your case you should write query as following:
"SELECT a.id, a.text, a.uid, a.time
FROM story a INNER JOIN friends b
ON a.id = b.some_id WHERE ((a.uid = '" . $uid . "') OR
(b.uid = '" . $uid . "' AND accepted='1') OR
(b.fid = '" . $uid . "' AND accepted='1'))
ORDER BY a.time DESC
LIMIT 3";
I think it will help.
I'm having a problem trying to count the number of user records according to the user's id, however I'm using a subquery to join 2 tables that one has a count parameter but I get an error saying duplicate column name 'user_id.
The query:
$sql = "SELECT loc.location_id,
COUNT(loc.location_id) AS total_records
FROM locations loc
LEFT JOIN
(
SELECT usr.*,
loc.*
FROM
(
members usr
INNER JOIN locations loc
)
WHERE usr.user_id = " . $user_id . "
AND usr.account_disabled = 0
ORDER BY loc.submit_date DESC
) usr ON (loc.user_id = usr.user_id)";
All I need it is to return the user's info and the total_records count done by the COUNT function.
Cheers.
EDIT:
This is what I get returned for this SQL:
SELECT loc.location_id,
loc.street_name,
loc.city,
loc.state,
loc.county,
loc.country,
usr.user_id,
usr.username,
COUNT(loc.location_id) AS total_records
FROM locations loc
INNER JOIN members usr ON (loc.user_id = usr.user_id)
WHERE loc.user_id = $user_id
AND usr.account_disabled = 0
GROUP BY loc.location_id
It's not exactly clear why you've got the derived resultset or the LEFT JOIN. Try this:
SELECT loc.location_id,
COUNT(loc.location_id) AS total_records
FROM LOCATIONS_TABLE loc
INNER JOIN MEMBERS_TABLE usr
ON (loc.user_id = usr.user_id)
WHERE loc.user_id = $user_id
AND usr.account_disabled = 0
GROUP BY loc.location_id
I think the problem is this part:
SELECT usr.*,
loc.*
Both tables have a user_id