tags:

views:

51

answers:

5

I have a DB with a table that is named "victim". The form that dumps the info into the table has room for two victims and therefore there is vic1_fname, vic1_lname, vic2_fname, vic2_lname, etc.. (business name, person first, person last, address, city, state, zip) a "1" and "2" of each. Now I want to search the DB and locate listed victims.

This is what I have so far:

$result = mysql_query(
                  "SELECT victim.*
                    FROM victim
                    WHERE vic1_business_name OR vic2_business_name  LIKE '%$search_vic_business_name%'
                    AND vic1_fname OR vic2_fname      LIKE '%$search_vic_fname%'
                    AND vic1_lname OR vic2_lname      LIKE '%$search_vic_lname%'
                    AND vic1_address OR vic2_address  LIKE '%$search_vic_address%'
                    AND vic1_city OR vic2_city        LIKE '%$search_vic_city%'
                    AND vic1_state OR vic2_state      LIKE '%$search_vic_state%'
                    AND vic1_dob OR vic2_dob          LIKE '%$search_vic_dob%'

                  ");

<table width="960" style="border: groove;" border=".5">
<tr><th colspan=10>You search results are listed below:</th></tr>
<tr>
<th>Case Number</th>
<th>Business Name</th>
<th>First Name</th>
<th>Last Name</th>
<th>DOB / Age</th>
<th>Address</th>
<th>City</th>
<th>State</th>
</tr>

<?php

while($row = mysql_fetch_array($result))
  { ?>

<tr>
<td align="center"><?php print $row['vic_business_name']; ?></td>
<td align="center"><?php print $row['vic_fname']; ?></td>
<td align="center"><?php print $row['vic_lname']; ?></td>
<td align="center"><?php print $row['vic_dob']; ?></td>
<td align="center"><?php print $row['vic_adress']; ?></td>
<td align="center"><?php print $row['vic_city']; ?></td>
<td align="center"><?php print $row['vic_state']; ?></td>
</tr>

<?php  }    ?>
</table>

The info did not display in the table until I changed the table to this:

<tr>
<td align="center"><?php print $row['vic1_business_name']; ?></td>
<td align="center"><?php print $row['vic1_fname']; ?></td>
<td align="center"><?php print $row['vic1_lname']; ?></td>
<td align="center"><?php print $row['vic1_dob']; ?></td>
<td align="center"><?php print $row['vic1_adress']; ?></td>
<td align="center"><?php print $row['vic1_city']; ?></td>
<td align="center"><?php print $row['vic1_state']; ?></td>
</tr>

<tr>
<td align="center"><?php print $row['vic2_business_name']; ?></td>
<td align="center"><?php print $row['vic2_fname']; ?></td>
<td align="center"><?php print $row['vic2_lname']; ?></td>
<td align="center"><?php print $row['vic2_dob']; ?></td>
<td align="center"><?php print $row['vic2_adress']; ?></td>
<td align="center"><?php print $row['vic2_city']; ?></td>
<td align="center"><?php print $row['vic2_state']; ?></td>
</tr>

Now it displays both rows, even if its empty. It doesn't matter if the victim was listed originally as vic1 or vic2, i just want to know if they are a victim.

I hope this makes sense. I can't get it to display the way I want, line-by-line, irregardless of whether you are vic1 or vic2.

+1  A: 

You should possibly look at getting this into first normal form. At some point an incident will happen with 3 victims! This will make your search queries easier as well.

So your Victim table would be structured like

caseid (or whatever)
victimid
business_name 
fname
lname
address
city
state
dob

Edit Following discussion in comments.

You say "When I seach your name I discover all the times you were a victim." This implies that presumably you are storing the victim's details multiple times and each time they might be slightly different.

This is definitely far from ideal and again seems like it could benefit from having normalisation principles applied but it really depends upon the scope of your application.

If it is essentially just a system for recording values entered on paper forms (whatever they may be) and doesn't try and link these together and resolve any such discrepancies then you may be fine with what you've got and using the syntax in Ignacio's answer. Which will resolve the question you actually asked!

The alternative is more flexible but might add quite a lot of unneeded complexity.

Martin Smith
I apologize, I am having trouble getting this to post correctly. It is actually missing some of the code.What do you mean "normal form" and the input form only allows for 2 victims. 3 Victims will not happen on this document.I have considered having a table for each victim listing, vic1, vic2, and then joining. that would allow for future victim listings if they decide to do that.
George Garman
@George I've clarified a bit above. I'll add a bit more to it shortly.
Martin Smith
Take a look at Wrikken's and my solutions for better solutions, because your solution would move the problem from adding *fields* to adding *tables*, which is expensive. Our solutions involve adding *rows*, which is what a DBMS is for, eventually.
MvanGeest
+2  A: 

You can't write queries like that.

WHERE ((vic1_business_name LIKE '%$search_vic_business_name%') OR
  (vic2_business_name  LIKE '%$search_vic_business_name%')) AND
 ....
Ignacio Vazquez-Abrams
+1  A: 

I think OR is a strictly boolean operator and therefore cannot be used to return a string for LIKE to match. You'll have to duplicate all the expressions, i.e. change

AND vic1_fname OR vic2_fname      LIKE '%$search_vic_fname%'

into

AND vic1_fname LIKE '%$search_vic_fname%' OR vic2_fname LIKE '%$search_vic_fname%'

BUT, as Martin Smith and knittl remark so correctly, this is a very inflexible and hard to use solution! What you could better try is to create separate incidents and victims tables and give the victims table a incident_id field which connects it to an incident. That way, you can assign any number of victims to an incident. (It's also possible to craft a system that allows a victim to appear in more than one incident, but that involves an additional table.)

MvanGeest
With every incident there is a case number. So each person is being added to the victim table with an auto-inc id number and the associated case number. There are a total of 9 tables so far in the DB (incident details, victim, arrestee, evid, etc.) the case number for each incident separates "you" in todays incident from the incident "you" were in last week.
George Garman
Very well then, so why do you need vic1 and vic2? Simply select all victims for who the case number is equal to (theoneyouneed) to get the victims for one case, and use one row per victim. Or am I missing something here?
MvanGeest
@MvanGeest I can see that the way it is coming back from the database at the moment is in a nice format to create the table in PHP.
Martin Smith
It's not you, it's my explanation. If I don't know the case number, but I know "you" were a victim, I search on your name and find the case number. When I seach your name I discover all the timies you were a victim. Once I figure this out I will apply the same to the arrestee/suspect search. Now I hate to admit it, but I did the same thing with the arrestee table as I did with the victim table.
George Garman
Yes, *that* is certainly one thing to consider. But designing applications is a mix of compromises and trade-offs. Is retrieving done more often that adjusting the requirements? Probably yes. Is using joins to give you your data slower than pulling these columns? Probably a teeny bit. Is searching done more often than inserting? Probably **yes**, and search speed would benefit from a single-row scheme more than insert speed would suffer. But of course, it's up to you :) Eventually, since none of these operations runs *all the time*, I'd go for the most flexible design.
MvanGeest
@George - So presumably you are storing the victim's details multiple times and each time they might be slightly different? Is it essentially just a system for recording values entered on paper forms (whatever they may be) or does the system try and link these together and resolve any such discrepancies?
Martin Smith
+1  A: 

Those victims should really have seperate rows in a table...

At the moment, the only way to get it working fast is using:

 SELECT ...
 FROM victim
 WHERE vic1_business_name LIKE '%$search_vic_business_name%' -- etc.
 UNION 
 SELECT ...
 FROM victim
 WHERE vic2_business_name LIKE '%$search_vic_business_name%' -- etc.

But it's cumbersome and not advisable. A seperate table victims, with a victim_relations table joining the 2 together would do the trick.

Wrikken
+1 but victim_relations might not be required as we don't know if it is 1-to-many or many-to-many
Martin Smith
I will seperate the two into two tables (victim1 victim2) and then join as you have suggested. Thank you for your help.
George Garman
@George - That wasn't the suggestion! Just to be clear there is no semantic difference between victim1 and victim2? When there are 2 victims it's arbitrary whether they are victim1 or victim2?
Martin Smith
No, his suggestion was a separate table for all victims and a many-to-many join table, which is rather odious to implement and apparently unnecessary in this case. On the other hands, victim1 and victim2 is (I think) illogical. If victim1 is not 'worth less than victim2' in real life, your DB design shouldn't make that distinction either.Also, be sure to know the difference between a `UNION` and a `JOIN`; he suggests a `UNION` as a quick fix if you don't want to change the table structure.
MvanGeest
Sorry Martin Smith, took me a long time to write the comment, and I wrote the same in more words :(
MvanGeest
Well, indeed, in one-to-one one could also have a victim_rel column in victims setting it to an id of the relation. Might be more appropriate indeed. And as everyone has sais: no 2 tables fof victims, just the single one.
Wrikken
+1  A: 

You could try getting your victims into a more useable form first:

((SELECT vic1_business_name, vic1_fname, vic1_lname, vic1_address, vic1_city, vic1_state, vic1_dob)
UNION
(SELECT vic2_business_name, vic2_fname, vic2_lname, vic2_address, vic2_city, vic2_state, vic2_dob))

Using that in a FROM expression should give you a list of all victims, one per line.

VeeArr
So you are suggesting I have a separate table for each victim?
George Garman
No, I'm suggesting you use the union that I provided to search through (as if it were the victims table itself). The select union I provided gives the same data as your original table, but splits it up one victim per line.
VeeArr