【问题标题】:pdo select a row if it contains one word of a stringpdo 选择一行,如果它包含一个字符串的一个单词
【发布时间】:2017-06-30 00:36:29
【问题描述】:

我有一个 mysql 表,其中用户有一个列有最喜欢的游戏。 它们是这样保存的:

id     username     games
1      user1        ,game1, game2, game3
2      user2        ,game2, game4
3      user3        ,game4, game1, game3

现在我想选择所有与我至少有一款游戏相同的用户。

$mygames = ,game2, game5

$statement = $pdo->prepare("SELECT * FROM users WHERE games = ?????");
$statement->execute();
$users = $statement->fetchAll();

它应该给我 user1 和 user2 因为两者都包含 game2 和我也! 我该怎么做?

感谢您的帮助:)

【问题讨论】:

  • 将游戏存储为 csv 是一个糟糕的设计。将它们存储为单独的多行,可以更轻松地进行这些类型的搜索。
  • 由于您的数据模型违反了关系数据库设计背后的理念,您现在遇到了一个问题,使查询变得非常复杂和昂贵。我建议您重新设计数据并将游戏移动到单独的关系表中。这样,您的查询将变得像一个简单的 WHERE 子句一样简单。
  • @arkascha - 是和否... MySQL 5.7 支持 JSON 字段类型,postgre 也是如此。这打破了关系数据库设计的规则。取决于您存储的数据以及您将如何查询 - 那么上述实现可能就完全没问题了。为了连接和增加不必要的复杂性而添加连接是没有意义的。例如如果表很小。此外,有时,不完全标准化可能更有效。
  • @Gravy 我不想争论每一种情况。但请注意,OP 存储的是 not json,它是类似于 csv 数据的半熟的东西。这不是有效的尤其是在 OP 所处的情况下。
  • @arkascha - 我同意你的看法。但是您不知道 OP 从哪里获得数据,这不是问题的一部分。顺便说一句,我也赞成你的评论。

标签: php mysql string select pdo


【解决方案1】:

尝试使用 Like 语句,示例:

$query = "SELECT * FROM users WHERE game LIKE ? OR game LIKE ?";
$params = array("%,game2%", "%,game5%");
$statement = $handle->prepare($query);
$statement->execute($params);

【讨论】:

    【解决方案2】:

    正如马特所说,使用 LIKE 语句

    以更好且可扩展的方式:

    $mygames = ",game2, game5"; // or whatever
    
    // split & trim the gamenames
    $games = array_map('trim',split(trim($mygames, ','))); 
    
    // for ANY number of games you have, set the condition that selects anyone who have ANY of them.
    $statement = $pdo->prepare("SELECT * FROM users WHERE " . substr(str_repeat(" games LIKE ? OR ", count($games)), 0, -3));
    $statement->execute();
    $users = $statement->fetchAll();
    

    【讨论】:

    • 另外,最好重新设计数据库的结构,这样您就不会将游戏名称存储在以 , 分隔的一列中。
    • “你的意思是“更好”、可扩展且不安全的方式?
    【解决方案3】:

    我找到了解决办法

    $mygames = ,game2, game5
    $ug = explode(",", $mygames); //each word is splitted at the ,
    $ug = array_filter($ug); //every empty array is deleted
    
    $statement = $pdo->prepare("SELECT * FROM users");
    $statement->execute();
    $users = $statement->fetchAll();
    
    foreach ($users as $row) { 
    
    $usg = explode(",", $row['games']); //each word is splitted at the ,
    $usg = array_filter($usg);          //every empty array is deleted
    $gsame= count(array_intersect($usg, $ug)) > 0; //if a user has at least one game as me it counts(onegame=1, twogames=2 etc...)
    
    if($gsame > 0) { //if gsam is more than 0 it displays the array
    <html></html>
    }
    

    希望这对你们中的一些人有所帮助:)

    【讨论】:

      【解决方案4】:

      你可以使用正则表达式吗?

      select * FROM users where games REGEXP 'game4|game2'; 例如,如果您想要所有包含 game4 或 game2 的行。

      所以你的 php 需要构造正则表达式。

      <?php
      
      $games = ['game2', 'game4']; // an array of the required games
      
      $regexp = implode('|', $games); // converts array to string with pipe as delimiter
      
      echo ($regexp); // outputs 'game2|game4'
      

      所以你的mysql现在变成了

      $sql = 'select * FROM users where games REGEXP '. $regexp .';

      【讨论】:

        猜你喜欢
        • 2012-08-05
        • 1970-01-01
        • 1970-01-01
        • 2014-03-06
        • 1970-01-01
        • 2012-11-21
        • 2021-03-07
        • 2016-12-14
        • 2012-02-25
        相关资源
        最近更新 更多