简体   繁体   中英

How to SELECT one field form one table which is part of string contained in one field of another table?

use PHP and MYsql. I have 2 tables like

  • table 'tag': has field 'id' and 'tag' ('tag' is varchar)

  • table 'entry': has fields 'tags' and other fields ('tags' is varchar that stores many words as tag, each word is separated by comma. Then I use function 'explode' to extract tags from string to store in array '$tags'. All tags from table 'entry' are stored in table 'tag'.)

What I want is to select all 'tag's from table 'tag' which are tags in the same string of 'tags' of table 'entry' that has a given tag (variable $tag). But no idea, I just try to SELECT tag from table 'entry' which string in 'tags' contains a specified tag (variable $tag).My current code is

$count=0;
$sql="SELECT tags FROM entry WHERE tag LIKE '%$tag%'";
$result = mysql_query($sql);
while($data=mysql_fetch_array($result)){
  if(mysql_num_rows($result)!=0){
    $tags1=explode(',',$data['tags']);
    for($loop=0; $loop<=count($tags1)-1; $loop++){
      if(!in_array($tags1[$loop], $tags2)){
        $count+=1; 
        $tags2[$count]=$tags1[$loop];
      }
    }
  }
}

The super inefficient, SQL injection attack prone way of doing it as one statement would be:

$sql="SELECT tags FROM entry WHERE 1=1 ";

Then add each tag to the query before running it:

$sql.="AND tag LIKE '" . $tags1[$loop] . "' ";

If you want to match any tag instead of all tags replace AND with OR .

I'd really suggest normalizing the tags and looking into not building SQL queries that way though.

The difficulties you are having solving this problem all stem from the fact that you're storing a list of tags in a single column.

You really need to add an intersection table, to contain the data for the many-to-many relationship between tags and entries. This is the proper way to design a relational database, and many SQL queries will become more efficient if you do that.

For example, to get all the tags from an entry that matches tag $tag :

<?php

$sql = "SELECT t1.tag FROM tag AS t1
INNER JOIN entries_tags AS e1 ON e1.tag = t1.id
INNER JOIN entries_tags AS e2 ON e2.entry = e1.entry
INNER JOIN tag AS t2 ON t2.id = e2.tag
WHERE t2.tag = ?";

$stmt = $pdo->prepare($sql);
$result = $stmt->execute( array($tag) );

$data = $result->fetchAll();
$count = count($data);

I wrote a chapter to detail the practical problems caused by this design in my book, SQL Antipatterns: Avoiding the Pitfalls of Database Programming .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM