$sSql = "SELECT COUNT(DISTINCT `tsu`.`id`) AS `count`
FROM `" . $this->_sPrefix . "users` AS `tsu`
INNER JOIN `" . $this->_sPrefix . "entries` AS `tse`
ON `tsu`.`id`=`tse`.`subscriber_id`
AND `tse`.`subscriber_type`='" . BX_DOL_SBS_TYPE_VISITOR . "'
WHERE 1
GROUP BY `tsu`.`id`
LIMIT 1";
Instead of counting the entries, it only returns 1. If I remove the group BY clause then it works. How can I fix the GROUP BY to make it work better?
The WHERE 1 does nothing, so it can be removed.
The GROUP BY can also be removed since you are not grouping by anything, your COUNT DISTINCT is on the whole table, no?
As Orbling points out, the LIMIT 1 can be removed too because COUNT DISTINCT returns only one value by definition.
Does it do what you want then?
You are grouping by tsu.id.
Each individual tsu.id group will by definition only have 1 distinct tsu.id in the group what do you expect it to return?
SELECT u.id, COUNT(e.id)
FROM users AS u
INNER JOIN entries AS e ON e.subscriber_id = u.id
WHERE e.subscriber_type = 'BX_DOL_SBS_TYPE_VISITOR'
GROUP BY u.id
Related
Hi I've got a query which does what I want to by displaying reviews which are rated first then followed by reviews which have yet to be rated. However I can't seem to get it to order correctly.
What the result should look like:
5
4
0
0
...
At the moment it is doing this:
4
5
0
0
...
Here is my query
$sql = $db->query( "
SELECT branch.*, MAX(review.rating) AS m
FROM branch
LEFT OUTER JOIN review ON branch.bid = review.bid
WHERE branch.address2 LIKE '$query' OR branch.postcode LIKE '$query-%'
GROUP BY branch.bid
ORDER BY m DESC, branch.branch ASC
LIMIT $start,$limit
" ) or die( "Select failed: (" . $db->errno . ") " . $db->error );
Sub-query solution by Meghraj Choudhary should work.
However, Joins are faster. Sub-queries require additional disk accessing. Assuming branch.bid is a primary key the following should be faster:
SELECT b1.*, b2.m FROM branch b1
INNER JOIN
(
SELECT branch.bid, MAX(review.rating) AS m
FROM branch
LEFT OUTER JOIN review ON branch.bid = review.bid
WHERE branch.address2 LIKE '$query' OR branch.postcode LIKE '$query-%'
GROUP BY branch.bid
LIMIT $start,$limit
) b2 ON
b1.bid = b2.bid
ORDER BY b2.m DESC, b1.branch ASC
I have not tried this. So, please try it and post back.
I have two MySQL queries:
1) "SELECT ID,post_title,post_category,post_perma FROM ".TBL_POSTS."
WHERE published='1' AND page='0' ORDER BY ID DESC LIMIT 10"
2) "SELECT p.cat_ID,p.cat_nicename FROM ".TBL_CATEGORIES." n, ".TBL_CATEGORIES." p
WHERE n.lft BETWEEN p.lft AND p.rgt AND n.cat_ID='".post_category."' ORDER BY p.lft
First query selects posts and then second select the Path of the category by post_category please note that post_category will be taken from first query means post_category is common in both table.. in first table it is named as post_category and in second it is cat_ID
Right now I am running it in foreach loop which is not good. Also one thing to be noticed that second query will also return Array and that one array should correspond to post_category
Can any SQL expert help me?
Many Thanx
Please try this it might be helpful to you.
SELECT a.ID, a.post_title,a.post_category,a.post_perma, b.cat_ID, b.cat_nickname
FROM (SELECT ID,post_title,post_category,post_perma FROM ".TBL_POSTS." WHERE published='1' AND page='0' ORDER BY ID DESC LIMIT 10) a
LEFT JOIN (SELECT p.cat_ID as cat_ID,p.cat_nicename as cat_nickname FROM " . TBL_CATEGORIES . " n, " . TBL_CATEGORIES . " p WHERE n.lft BETWEEN p.lft AND p.rgt AND n.cat_ID = '" .$post_category. "' ORDER BY p.lft) b ON a.ID = b.cat_ID
I would use LEFT JOIN
Like this:
$sql = "SELECT `p`.`ID`,`p`.`post_title`,`p`.`post_category`,`p`.`post_perma`,`c`.`cat_ID`,`c`.`cat_nicename` FROM `".TBL_POSTS."` AS `p` ";
$sql .= "LEFT JOIN `".TBL_CATEGORIES."` AS `c` ON `c`.`cat_ID`=`p`.`post_category` WHERE `p`.`published`='1' AND `p`.`page`='0' ORDER BY `p`.`ID` DESC LIMIT 10";
You may need to tweak the WHERE clause to suite your needs more..
Please Note: This is one string, i have just split them onto two lines so it is easier to read. .= is to append the current string.
here is a small sample of what im trying.. as its hardly to code it here I have uploaded an image..
http://i46.tinypic.com/5bxn5u.png
just want to display the total number of reservations for each room.. thanks
You'll want to join the tables together and use COUNT() with a GROUP BY:
SELECT
a.id, a.name, COUNT(*) AS num_reservations
FROM
availables a
LEFT JOIN reservations r
ON r.available_id = a.id
GROUP BY
a.id
This should give you a list of each room with a total number of reservations each has.
To put it into your existing query, you can use the following:
$coordinator = (isset($_GET['uidse']) && is_numeric($_GET['uidse'])) ? (int)$_GET['uidse'] : 0;
$result = mysql_query("SELECT *, COUNT(*) AS num_reservations FROM availables LEFT JOIN reservations ON availables.id=reservations.available_id WHERE coordinator='" . $coordinator . "' GROUP BY availables.id");
I placed $coordinator outside of the MySQL query and added very basic validation/sanitization to save you from a SQL-Injection headache in the future.
SELECT availables.name, COUNT(*) FROM availables
LEFT JOIN reservations ON reservations.available_id = availables.id
GROUP BY reservations.available_id
$query = "SELECT DISTINCT t.task_id, e.url,e.error_id, p.page_rank, e.scan_status, e.url_is_route,e.url_is_route,e.forbidden_word,e.google_host_fail,e.google_cache_fail,e.google_title_fail,e.robots_noindex_nofollow,e.xrobots_noindex_nofollow,e.title_fetch_warn,e.h1_fail,e.h2_fail,e.h3_fail,e.h1_warn,e.h2_warn,e.h3_warn
FROM `error_report` AS e
INNER JOIN task_pages AS t ON t.task_id=e.task_id
INNER JOIN `pages` AS p ON p.page_id=t.page_id
WHERE t.task_id=" . $this->task_id ;
I want the query to be distinct only by t.task_id. The problem is that when I add more fields..the query isnt distinct anymore. Is there still a way to select distinct by t.task_id only?
instead of distinct use group by
$query = "SELECT t.task_id, e.url,e.error_id, p.page_rank, e.scan_status, e.url_is_route,e.url_is_route,e.forbidden_word,e.google_host_fail,e.google_cache_fail,e.google_title_fail,e.robots_noindex_nofollow,e.xrobots_noindex_nofollow,e.title_fetch_warn,e.h1_fail,e.h2_fail,e.h3_fail,e.h1_warn,e.h2_warn,e.h3_warn
FROM `error_report` AS e
INNER JOIN task_pages AS t ON t.task_id=e.task_id
INNER JOIN `pages` AS p ON p.page_id=t.page_id
WHERE t.task_id=" . $this->task_id
."group by t.task_id";
If you add more fields, you should use GROUP BY iirc.
Note that your extra fields should be aggregates, e.g. MIN, MAX, etc. MySQL is more forgiving and shows the first value of each field (though not reliably apparently).
I have a database named 'friends' and it has columns 'user_id' and 'friend_id'.
user_id is the invitor and friend_id the recipient. Please note that when a friendship is created I'm NOT making 2 records in the database like 1,2 and 2,1.
How to list all the friends of mine, considering that my users.user_id can vary between friends.friend_id and friends.user_id in the 'friends' table. Also how to join the query to the 'users' table to get the names of all my friends.
One option would be a union of two queries:
select u.name
from friends f
inner join users u
on f.user_id = u.user_id
where f.friend_id = #YourID
union
select u.name
from friends f
inner join users u
on f.friend_id = u.user_id
where f.user_id = #YourID
You should make a Join query to get the best performance. Try something like this:
$friends_result = mysql_query("
SELECT
users.`name` AS name
FROM
friends
LEFT JOIN
users
ON
users.`id` = friends.`user_id`
OR
users.`id` = friends.`friend_id`
AND
users.`id` != '" . $user_id . "'
WHERE
friends.`user_id` = '" . $user_id . "'
OR
friends.`friend_id` = '" . $user_id . "'");
echo "<strong>My friends:</strong><br />";
while($friends_array = mysql_fetch_array($friends_result))
{
echo $friends_array['name'] . "<br />";
}
I think it would probably be easiest to ensure that the friends table always has the lower ID in the user_id column and the higher one in the other.
This way, you do not need to check twice, thus achieving better performance.
However, this approach requires you to modify your friend-adding code and assumes that user IDs never change (or you have to update your IDs in the table).
Otherwise, use UNION queries like Joe said or to join using an OR condition (e.g. JOIN ... ON u.user_id = friends.user_id OR u.user_id = friends.friend_id) or IN (JOIN ... ON u.user_id IN (friends.user_id, friends.friend_id)), which might be expensive operations (use EXPLAIN and benchmarks to find out).