Three MySQL queries for one operation!? I think not - php

I'll try to be right to the point. Here's what I'm trying to do.
I have two tables that I need to pull data from:
membershipstable = || groupid || templateid || userid
|| 2 || 1 || 0
|| 0 || 1 || 3
|| 2 || 0 || 4
userstable = || id || firstname || lastname || email
What I would like to do would be something like:
SELECT * FROM userstable WHERE id = userid (in memberships table) -- AND/OR -- WHERE id = userid IF groupid is associated with templateid, and templateid is equal to $currenttemplateid
Or in human speak: Look at the memberships table and if you find a row containing a templateid that matches $currenttemplateid then bring back the userid from that row. Then, look at the userstable and retrieve the information for each user who has an id matching a userid we found above. Also, if you find any rows that contain a templateid that matches $currenttemplateid, then look at the groupid in that row and bring back any userid that is in any row with that groupid, and again retrieve the information for any user with an id that matches the userid that was found above.
I'm sorry if my explanation is somewhat confusing, and if my question reeks of newbishness (also, don't worry, I'm not using unprepared statements in the actual project)... I know that this can be done with MySQL in a single, efficient, and beautiful query but I'm at a complete loss as to what exactly that query would look like... Thank you very much for your help. :)

Use a 3-way join to find all the users in the same group as the selected member.
SELECT u.*
FROM usertable AS u
JOIN membershiptable AS m1 ON u.id = m1.userid
JOIN membershiptable AS m2 ON m1.groupid = m2.groupid
WHERE m2.templateid = $currenttemplateid
DEMO

For anyone who may come looking for the answer at a later time, there is the concern of ending up with duplicate entries in the return if a user has been assigned to both a template and a group that is also assigned to the template. A solution for this is to put DISTINCT directly after the SELECT portion of the query. E.g.
$query = "
SELECT DISTINCT
u.id,
u.firstname,
u.lastname,
u.username,
u.email
FROM $userstable AS u
INNER JOIN $membershipstable AS M1 ON u.id = M1.userid
INNER JOIN $membershipstable AS M2 ON M1.groupid = M2.groupid
WHERE M2.templateid = :currenttemplateid
";
This returns only non duplicate results.

Related

What join to use

I have two tables, one for registered users and one to store votes.
We are logging in with registrants.id and registrants.zipcode. Once they vote their votes are inserted into the votes table, along with their Registration ID.
Im trying to right a select statement that returns a record that will select all the records for Matched ID and Zipcode, but the ID is not in the Votes.voter column. i have tried all kinds of variations of all the joins i can think of. is it something simple i am missing.
SELECT * FROM registrants
LEFT JOIN votes on registrants.id = votes.voter
WHERE registrants.id = 1 AND registrants.zipcode = 46706 and votes.voter <> 1
Perhaps a not exists query:
select * from registrants
where registrants.zipcode = '46706'
and not exists (select 1 from votes where registrants.id = votes.voter)

Distinct Values from MySQLi Query

I am trying to only show unique userIds (userIds are (0,1,2,3,4,5,6,7,8,9 etc...) for the query I am running. I tried using DISTINCT in my query, but it only shows me unique values of the rows that have 2 or more of the same userId.
Is there a way I can use php to only show the unique values. My weak points are arrays and it makes it more complicated because its using data from a MySQLi query.
Example right now I have with the query now (lets say its GROUP BY rentPaid DESC and the rent total is 800.00 for all users):
userID rentPaid rentMonth
2--------800.00------April
1--------500.00------April
3--------400.00------April
3--------400.00------April
1--------200.00------April
1--------100.00------April
Example desired output:
userID rentPaid rentMonth
2--------800.00------April
1--------500.00------April
3--------400.00------April
Can I do this with MYSQL because I tried DISTINCT and it wouldn't work, how about PHP?
Query:
SELECT
properties.*,
leases.*,
users.userId, users.primaryPhone,
CONCAT(users.userFirstName,' ',users.userLastName) AS user,
admins.adminName, payments.*
FROM
properties
LEFT JOIN leases ON properties.propertyId = leases.propertyId
LEFT JOIN assigned ON properties.propertyId = assigned.propertyId
LEFT JOIN admins ON assigned.adminId = admins.adminId
LEFT JOIN users ON properties.propertyId = users.propertyId
LEFT JOIN payments ON properties.propertyId = payments.propertyId
WHERE
payments.rentMonth = '$currentMonth' AND
payments.rentYear = '$currentYear'
Edit: Please excuse my formatting, this is my first post.
Edit: Added query....its long, but works lol. I only want unique userIds (no double or triple userIds etc...)
I suspect this is what you want:
SELECT userID, MAX(rentPaid) AS maxRentPaid, rentMonth
FROM yourTable
WHERE rentMonth = "April"
GROUP BY userID
ORDER BY maxRentPaid

Left join with filter

I'm trying to display a list of books from a table (books) but I want to display the name of the book in green if the user connected added the book in his collection. The collections are in the table collection. So I need to retrieve all the informations from the books table but I need to differentiate the books owned by the user.
I tried something like this :
SELECT * FROM books LEFT JOIN collection ON books.ID = collection.ID_book AND collection.ID_member = :ID_member WHERE books.ID_author = :ID_author
:ID_member is the ID in session of the member logged in and ID_author is the name of the author I want to display the list. But with that query, I cannot retrieve the ID of books that the user doesn't own. Do you have an idea to retrieve these ID too ?
I thought of a second query inside the while() but that would means a query PER book...
EDIT (more informations) :
I have a table books with all the informations concerning the books.
Then, I have a table collection with these columns : ID, ID_member, ID_book
With my query, if I want to display all books from... let's say Stephen King, I have something like this :
book || ID of the book || book owned by the user
1 || 1 || 0
2 || 2 || 0
3 || || 1
4 || 4 || 0
5 || || 1
6 || 6 || 0
The ID I want to display is the collection.ID_book because if I display ID, it will show collection.ID
So as you can see when the user own the book I can't have the ID of the book... but I can display the other informations (like the book title) because the other informations are taken from the books table and the ID from the collection table... Too bad that it's not possible to chose the table in the
I understand that the problem is that the ID column exists in both tables. One solution may be to duplicate the ID column, like ID2. Then it will work because ID2 doesn't exist in the collection table. But that is maybe too much...
Thank you for your help.
Regards.
It is very easy to set columns up with aliases:
SELECT books.ID AS book_id, collections.id AS collection_id
FROM books
LEFT JOIN collection ON books.ID = collection.ID_book AND collection.ID_member = :ID_member
WHERE books.ID_author = :ID_author
After you have done this your column names will be book_id and collection_id and since they are no longer duplicate names (with one overwriting the other) you can access each of them.
Then if you know that you want all the columns from books but only the idcolumn from collection you can do something like this:
SELECT books.*, collections.id AS collection_id
FROM books
LEFT JOIN collection ON books.ID = collection.ID_book AND collection.ID_member = :ID_member
WHERE books.ID_author = :ID_author
I think your query should be doing what you want. I suspect that the problem may be the select * and multiple columns with the same name. Does this query do what you want?
SELECT b.*,
(case when c.ID_book is not null then 'GREEN' else 'NOT OWNED' end) as color
FROM books b LEFT JOIN
collection c
ON b.ID = c.ID_book AND c.ID_member = :ID_member
WHERE b.ID_author = :ID_author;
I think you can solve this problem by changing your query slightly, maybe give this a try.
SELECT * FROM books
LEFT JOIN collection ON books.ID = collection.ID_book
WHERE books.ID_author = :ID_author OR collection.ID_member = :ID_member
When joining on the condition of the user id, you're only going to have those rows available in the result set. By moving that condition to the WHERE clause using the OR operator, you can have both conditions met.
NOTE: Try not to use SELECT *.
SELECT * FROM books LEFT JOIN collection
ON books.ID = collection.ID_book
INNER JOIN member ON collection.ID_member = member.:ID_member WHERE books.ID_author = :ID_author
would you try that sir.. I'm not sure though. I'm assuming that the ID_member fields came from a member table.. and the ID_member to collection table is a foreign key..

PHP/MySQL Using multiple WHEREs in one SELECT query

I have 2 tables.
Table A: trades: which contains the columns: tradeID, tradeName, tradeShow, and tradeGuy.
Table B: offers: which contains the columns: tradeID, offerName, offerGuy.
I'm trying to select all columns from table A (trades) WHERE the value of "tradeShow" = 'Yes', And the value of "tradeGuy" != the user's Username. That much is easy, but I also don't want to select any records which have an offer created by the user. In other words, in table B (offers), offerGuy != Username WHERE trade ID from Table B = tradeID from Table A.
But, how do I merge these 2 conditions? I've tried this:
$sql = "SELECT *
FROM trades t1
JOIN offers t2
ON (t1.tradeID = t2.tradeID)
WHERE t1.tradeShow='Yes' AND t1.tradeGuy!='$username' AND t2.offeringGuy!='$username'";
But the problem with that is it only selects the records from trades which have an offer, because of the forth line: ON (t1.tradeID = t2.tradeID), as in it only selects trades which have a record in (offers) that mentions their tradeID.
I've also tried an awkward attempt to link the 2 tables with a meaningless link by adding a "linker" column to each table with the default value of "XXX", and did this:
$sql = "SELECT *
FROM trades t1
JOIN offers t2
ON (t1.linkerA = t2.linkerB)
WHERE t1.tradeShow='Yes' AND t1.tradeGuy!='$username' AND (t2.offeringGuy!='$username' WHERE t1.tradeID=t2.tradeID)";
But the problem with that is using 2 Where clauses...
So, how do I merge the 2 conditions?
What you're looking for is called an OUTER JOIN (in this case a LEFT OUTER JOIN) which will give you null results for missing matches, something like;
SELECT *
FROM trades t1
LEFT OUTER JOIN offers t2
ON t1.tradeID = t2.tradeID AND t2.offeringGuy = '$username'
WHERE t1.tradeShow='Yes' AND t1.tradeGuy!='$username' AND t2.offeringGuy IS NULL
We add a condition to the LEFT JOIN that we're only interested in matches against t2.offeringGuy = '$username', which will return NULL values in t2's fields if there is no match.
Then we just check that t2.offeringGuy IS NULL to find the non matches.
I would do this with not exists rather than an explicit join:
SELECT *
FROM trades t
WHERE t.tradeShow = 'Yes' AND t.tradeGuy <> '$username' and
not exists (select 1
from offers o
where t.tradeID = o.tradeID and o.tradeGuy = '$username'
);

PHP MySQL - Select members with where-clause statements from different tables

I've been Googling for most of my day now but I can't seem to find the right answer. Maybe because I don't really know in which direction to look (join? exist?). What I have is 3 tables:
There is a table named 'groups' and 'languages' containing the actual group- and language data but that's not important right now.
The user should be able to generate a list with all members, depending on the selected groups and/or languages. The groups/languages that the user selected are saved in two separate array's containing the IDs ($aGroups and $aLangs).
What I want/need is to SELECT * FROM members WHERE ...
And that's where I got stuck. I've tried joins, I've tried IN(), I've tried EXIST but nothing seems to work right.
Any help is greatly appreciated!
If you want to select members by languages and groups, you can do something like this :
$query = "select * from members as m
left join group_members as gm on gm.member_id = m.id
left join language_members as lm on lm.member_id = m.id";
if(isset($aGroups)) {
$query .= " where group_id in (".implode(",", $aGroups).")";
if(isset($aLangs)) {
$query .= " and language_id in (".implode(",", $aLangs).")";
}
}
elseif(isset($aLangs)) {
$query .= " where language_id in (".implode(",", $aLangs).")";
}
I think you just need some brackets:
//assuming you have ids stored in $lang and $group
SELECT * FROM members WHERE (SELECT group_id FROM group_members WHERE member_id=members.id)='$group'
AND (SELECT lang_id FROM language_members WHERE member_id=members.id)='$lang'
The trick is "members.id", DB will call subquery for every member to find out if the condition for group and lang is met.
Select m.* FROM members m, group_members gm, language_members lm
WHERE
lm.member_id=m.id AND
m.id=gm.member_id AND
<<<< START YOUR OWN WHERE HERE.

Categories