views:

743

answers:

2

I'm trying to figure out how to get a select statement to be populated by an ever-changing number of where's. This is for an order-status tracking application.

Basically, the idea is a user (customer of our company) logs in, and can see his/her orders, check status, etc. No problem. The problem arises when that user needs to be associated with multiple companies. Say they work or own two different companies, or they work for a company that owns multiple sub-companies, each ordering individually, but the big-shot needs to see everything ordered by all of the companies. This is where I'm running into a problem. I can't seem to figure out a good way of making this happen. The only thing I have come up with is this:


client='Client Name One' OR client='Client name two' AND hidden='0' OR client='Client name three' AND hidden='0' OR client='Client name four' AND hidden='0'

(note that client in the previous code refers to the user's company, thus our client)

placed inside of a column called company in my users table of the database. This then gets called like this:


$clientnamequery = "SELECT company FROM mtc_users WHERE username='testing'";
$clientnameresult = mysql_query($clientnamequery);  list($clientname)=mysql_fetch_row($clientnameresult);

$query  = "SELECT -redacted lots of column names- FROM info WHERE hidden='0' AND $clientname ORDER BY $col $dir";
$result = mysql_query($query);

Thing is, while this works I can't seem to make PHP add in the client=' and ' AND hidden='0' correctly. Plus, it's kind of kludgy.

Any ideas? Thanks in advance!

A: 

You can use the IN keyword

client IN('client1','client2',...)
Tim
That doesn't seem to work. It should be noted, the column it's comparing against only has one client's name in it (in the orders table). So the idea is it shows this user all the orders from client one and client two and client three and so on.However, I couldn't find a mysql page talking about IN, but it is a very popular word...
Cameron Conner
Doc for IN operator: http://dev.mysql.com/doc/refman/5.0/en/comparison-operators.html#function_in
outis
+1  A: 

Expanding on Tim's answer, you can use the IN operator and subqueries:

SELECT *columns* FROM info 
  WHERE hidden='0' AND client IN
  (   SELECT company FROM co_members 
        WHERE username=?
  )
  ORDER BY ...

Or you can try a join:

SELECT info.* FROM info 
  JOIN co_members ON info.client = co_members.company
  WHERE co_members.username=?
    AND hidden='0'
  ORDER BY ...

A join is the preferred approach. Among other reasons, it will probably be the most efficient (though you should test this with EXPLAIN SELECT ...). You probably shouldn't grab all table columns (the info.*) in case you can later change the table definition; I only put that in because I didn't know which columns you wanted.

On an unrelated note, look into using prepared queries with either the mysqli or PDO drivers. Prepared queries are more efficient when you execute a query multiple times and also obviate the need to sanitize user input.

The relational approach involves tables like:

CREATE TABLE mtc_users (
    username PRIMARY KEY,
    -- ... other user info
) ENGINE=InnoDB;

CREATE TABLE companies (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR() NOT NULL,
    -- ... other company info
) ENGINE=InnoDB;

CREATE TABLE co_members (
    username NOT NULL,
    company NOT NULL,
    FOREIGN KEY (`username`) REFERENCES mtc_users (`username`) 
        ON DELETE CASCADE
        ON UPDATE CASCADE,
    FOREIGN KEY (`company`) REFERENCES companies (`id`) 
        ON DELETE CASCADE
        ON UPDATE CASCADE,
    INDEX (`username`, `company`)
) ENGINE=InnoDB;

If company names are to be unique, you could use those as a primary key rather than an id field. "co_members" is a poor name, but "employees" and "shareholders" didn't quite seem the correct terms. As you are more familiar with the system, you'll be able to come up with a more appropriate name.

outis
How should the companies in the company column be laid out (in mtc_users) in the database to work?
Cameron Conner
The table should hold the user<->company relationship, with a row for each company a user is a part of. If mtc_users holds users' properties (1 row for each user), create a new table and use that instead.
outis
outis, you're awesome.
Cameron Conner