How to combine these 2 queries into 1 and avoid extra code - php

I have 2 tables in database, table users lists all users and their inviters (referrers) , table donations lists all the donations
The only connection between 2 tables is the user_id in table donations which is the id (Primary AI) in table users
What i want to do is get count of all users in table users which have ref='$referrer' and then see how many of them have donated and they are in donations table (each user can donate multiple times so it shouldn't count 2 donations as 2 users)
What i have tried:
first i get each ref of that inviter
SELECT id FROM users WHERE ref='$referrer'
then i put it in a while() loop and for each one of them i check if they have a donation
SELECT * FROM donations WHERE user_id='$id'
if they are found that counts as 1++
Issue
issue is if a user invited +500 people, then i send 500 queries in a loop with PHP, which takes time and resource
What is needed
I need a single Query with sub-Query to take only referrer id (ref='$referer') and give me count of all user X's referrals (every user with ref='55' in table users for example) which also have at least one donation in donations table
something like:
SELECT COUNT(*) FROM donations WHERE user_id = (SELECT id as user_id FROM users WHERE ref='$referer')
Can any one please help me with that

SELECT COUNT(*) FROM donations d INNER JOIN users u ON d.user_id=u.id WHERE u.ref='$referrer' GROUP BY d.user_id

Try this:
SELECT users.id, COUNT(*) `donations_count`
FROM users
INNER JOIN donations ON user.id = donations.user_id
WHERE users.ref='$referrer'
GROUP BY users.user_id

Related

SQL - Return books that user owns

I'm doing I'm having a bit of a problem performing a query in my university project. I got a website where users share the books that they've read and I have a page where the user can view the books he has added (the books he owns).
For that I believe I need the logged user's id, which I store in a session PHP variable, the user id is in table users.
The information about the books is stored in a table books and it has its own id primary key.
Then, to show who owns what I have a table owns_book (id, u_id, book_id).
Right now for testing I've got 26 books total, 25 of them are added by a user with id of 57 and 1 book by user with id of 49.
When I run this query:
SELECT id, title, author, category, cover, added, user_id FROM books, users
WHERE user_id=49 AND id IN(SELECT book_id FROM owns_book)
AND user_id IN(SELECT u_id FROM owns_book)
And the result is a mess, I don't get the expected one book, I also get books added by the other user.
Can someone please show me the correct query that I need or if I need to change the structure of my tables? Thanks.
EDIT:
users(user_id, ...)
books(id, title, author, publisher, published, cover... )
owns_book(id, u_id, book_id)
It looks like you're looking to to grab everything from your books table that is owned by a specific customer. If that's the case, you can try
SELECT * FROM books
JOIN owns_book
ON books.id = owns_books.book_id
WHERE owns_book.user_id = 49
This will select all of the props from your books table then joins the tables based on on the ID of the book being equal to the book_id of the owns_book. Lastly, add the parameter - you only want to see user_id = 49.
You can simplify this query and use a LEFT JOIN...
SELECT books.id, title, author, category, cover, added, users.user_id
FROM users
LEFT JOIN owns_book on owns_book.user_id = users.user_id
LEFT JOIN books on books.id = owns_book.id
WHERE users.user_id=49
This links the user_id and lists any books owned by this user_id ( the ON bit of the JOIN). The WHERE clause just limits to listing records for the user_id your after.
If in the main list of columns, there is a column on multiple tables ( like user_id) then prefix it with the table name to allow the database to detect which column you want to use (even though they may be the same value).
You could also use inner join to join the tables users and books with the owns_book table:
SELECT id, title, author, category, cover, added, user_id
FROM owns_book
INNER JOIN users ON users.id = owns_book.u_id
INNER JOIN books ON books.id = owns_book.book_id
WHERE users.user_id=49

MySQL, combining DISTINCT and JOIN

I have a table of users, called ..wait for it... "users".. and then another table which records users' activity called ...you'll never guess... "activity"..
I have an HTML table which shows the users in the users table, but I want to order the table by the users' last activity.
Here's my query.
SELECT *
FROM `users`
JOIN `activity`
ON `activity`.`user_id` = `users`.`id`
ORDER BY `activity`.`timestamp`
LIMIT 25
The problem here is that it shows multiple rows for each user since there are multiple records for each user in the activity table.
How can I alter the query to only show one record for each user and order them by the last activity in the activity table.?
I did experiment with using the "DISTINCT" keyword but no luck :/
"one record for each user and order them by the last activity in the activity table.?"
Couly try this? Assuming you need both user info and activity info.
SELECT users.*, a.*
FROM users INNER JOIN (
SELECT user_id, MAX(timestamp) max_timestamp
FROM activity
GROUP BY user_id
) x ON users.user_id = x.user_id
INNER JOIN activity a ON x.user_id = a.user_id AND a.timestamp = x.max_timestamp
ORDER BY a.timestamp;
inner sub-query finds max_timestamp per user_id and outer JOIN finds activity has max_timestamp and user_id
This is not SQL solution, but what I would do is keep lastActivity column in Users table and update it when needed. Then sorting, filtering by this column would be very easy and efficient.

Inner, outer or full join on three tables in MySQL database on linux with apache

I want to have some help creating my query to get information from three different tables sharing information in common.
My first table is:
auctions
id title description user_id(who posted it)
My second table is:
bids
id user_id bid auction_id owner_id
My third table is:
users
id username X XX XXX XXXX
...and my SQL is as follows however it's not returning any results:
SELECT auction_bids.user_id AS applicant, auction_bids.*, auctions.title FROM auction_bids, auctions
WHERE auctions.user_id=".$_SESSION['userid']."
INNER JOIN users ON auction_bids.user_id = users.id
WHERE auction_bids.owner_id = ".$_SESSION['userid']."
What I need is to capture the auction's title, username who bidded on the auction and the bid. the auction has to have a bid and posted by the user who owns the $_SESSION['userid'].
Any help is appreciated.
You have two different 'where' statements, which may just need combining;
SELECT auction_bids.user_id AS applicant, auction_bids.*, auctions.title FROM auction_bids, auctions
INNER JOIN users ON auction_bids.user_id = users.id
WHERE auction_bids.owner_id = ".$_SESSION['userid']." AND auctions.user_id=".$_SESSION['userid']."
However, I'm not sure this is really what you want, as it will return only records where the specific user both 'owns' the item AND has bidded on it (both based on the userid session), rather than displaying all records from different people who have bidded on an item 'owned' by the user.
Something like: ?
SELECT auction_bids.user_id AS applicant, auction_bids.*, auctions.title FROM auction_bids, auctions
INNER JOIN users ON auction_bids.user_id = users.id,
WHERE auction.owner_id = ".$_SESSION['userid']."
Hope this points you in the right direction!
you have 2 where clauses, that is incorrect. I have revised your query based on your requirements.
SELECT auction_bids.user_id AS applicant, auction_bids.*, auctions.title
FROM auction_bids, auctions
INNER JOIN users ON auction_bids.owner_id = users.id
WHERE auction_bids.owner_id = ".$_SESSION['userid']."
AND auctions.user_id=auctions_bids.owner_id

PHP MySQL Active Record criteria sum

I have two tables, users and visits. I want to select all users who have 'active' in the visits table's status field, with a count of all visit records regardless of active/inactive status.
This query would only give me a count of 'active' visit records
SELECT
users.user_id,
COUNT(visits.id)
FROM users u
JOIN visits v ON v.user_id=u.user_id
WHERE visits.status='active'
I was thinking of a subquery, or a php loop but worried about performance if the users table grows. If subquery's the best solution please post the active record code.
A sub-query will be more efficient than looping in the code. I'd suggest this query:
select u.user_id, ucount
from users u
join (
select user_id, COUNT(id) as ucount
from visits
group by user_id
) all
ON u.user_id = all.user_id
join visits v
on v.user_id=u.user_id
where v.status='active'
And if you need only user_id and no users.* field, then you don't have to join to users table (inspired by answer from arunmoezhi):
select user_id,count(*) as visit_count
from visits v
join (
select user_id from visits
where status ='active'
) act
on v.user_id=act.user_id
group by v.user_id;
Edited for formatting.
select user_id,count(*) as visit_count
from visits
where user_id in(
select user_id from visits
where status ='active'
)
group by user_id;

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

Categories