GeorgeButter
GeorgeButter

Reputation: 2591

Select rows from a table based on results from two other tables in mySQL using PDO

I have structured my Database in 3 tables:

members       -       membersitems       -     items
---------------------------------------------------------
memberid      -       memberitemid       -     itemid
username      -       itemid             -     itemname
password      -       memberid           -     itemtype
etc

The idea is that every time a member gets a new item a row is added to membersitems. The membersitems table is intended to join the two tables. I'm not sure if there is a simpler way using only two table and JOIN?.

Using the $_SESSION["memberid"] I am selecting rows in the membersitems table where the memberid is the same as the session:

$stmt = $db->prepare('SELECT itemid FROM membersitems WHERE memberid = :memberid');
$stmt->execute(array(':memberid' => $_SESSION['memberID']));
$array = $stmt -> fetchAll(PDO::FETCH_ASSOC);
    foreach($array as $row) {
    $itemid[] = $row['itemid'];
}

I'm not sure the best way to collate this data for the next step, but I tried using a comma separated string:

$itemids = '[' .implode(',', $itemid). ']';
/// echos out: [1,2,3,4,5,6,6,6,]

Note there are three of item 6. I would like to display item 6, three times.

I am then trying to select the data in the items table using the following code, which isn't working, but isn't returning an error:

    $arr = $itemids;     
    $in  = str_repeat('?,', count($arr) - 1) . '?';
    $sql = "SELECT * FROM items WHERE itemid IN ($in)";
    $stm = $db->prepare($sql);
    $stm->execute($arr);
    $data = $stm->fetchAll();

I would also like some advice on separating the returned data and perhaps sorting by type.

I am quite new to server-side scripting and mySQL, but can handle criticism. Please be as critical as possible but assume my knowledge is basic. The accepted answer will be the one that is teaching rather than just a solution.

I know there are similar questions, I have tried other examples that are a similar concept to this but struggled to fill in the gaps where there were nuances.

Thank you in advance.

Upvotes: 1

Views: 223

Answers (2)

Nate Vaughan
Nate Vaughan

Reputation: 3839

As hinted in some of the comments, this is a very straightforward SQL concept called JOIN.

You are using WHERE IN which has a close cousin in the JOIN family called INNER JOIN.

You'll need to read some documentation on JOIN, but suffice it to say that INNER JOIN can be used to filter one table using another table. For example, if you want to get items out of your items table filtered by membersid from your join table, you could do so with a query like this:

SELECT i.* 
FROM items i
INNER JOIN membersitems m
ON i.itemid = m.memberid
WHERE m.memberid = :memberid

In most cases, this will be a much more efficient way to get the items associated with a given memberid than executing two queries (and as mentioned in the comments it's best to avoid comma-serializing ids in PHP and then requerying).

As a side note, a subquery would be another way to achieve your goal, using similar syntax to your current query:

SELECT * 
FROM items 
WHERE itemid 
IN (
  SELECT itemid 
  FROM membersitems 
  WHERE memberid = :memberid
)

One more note. Your table schema may be redundant depending on what kind of relationship you have between members and items. You'll want to do some reading on schema design for One-To-Many vs Many-To-Many. The design you have is a good one if it is possible for: 1) One member to have many items AND 2) One item to have many members However, if every item in the items table is associated with one and only one member (which I suspect might be the case), you could use a schema like this one:

members       -     items
------------------------------
memberid      -     itemid
username      -     memberid
password      -     itemname
etc

In the above schema, each item is responsible for knowing its parent member, and that is sufficient to execute both of the above queries (simply substituting the appropriate table names).

A final note. This is by no means a requirement, but it is pretty common for tables to simply have id columns called id (not itemsid, membersid). It's pretty common sql convention to separate words with underscores for join tables (e.g. items_id and members_id).

Have fun and good luck!

Upvotes: 1

RiggsFolly
RiggsFolly

Reputation: 94652

This I think is the query you are looking for. I was not totally sure what result you wanted but this should give you a push in the right direction.

$q = "SELECT i.* 
      FROM items i
          JOIN membersitems m ON m.itemid = i.itemid
      WHERE i.memberid = :memberid";



$stmt = $db->prepare($q);
$stmt->execute(array(':memberid' => $_SESSION['memberID']));

Upvotes: 1

Related Questions