pdo选择一行,如果它包含字符串的一个字

问题描述:

我有一个mysql表,其中用户有一列有喜欢的游戏列。 它们被保存这样的:pdo选择一行,如果它包含字符串的一个字

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和我呢! 我该怎么做?

感谢您的帮助:)

+0

存放场比赛作为CSV是一个糟糕的设计。将它们存储为单独的多行,可以更轻松地执行这些类型的搜索。 – Sean

+6

由于您的数据模型违反了关系数据库设计背后的想法,因此您现在遇到了一个问题,使得查询非常复杂且昂贵。我建议你重新设计你的数据并把游戏移动到一个单独的关系表中。这样你的查询就像简单的WHERE子句一样简单。 – arkascha

+0

@arkascha - 是和不是... MySQL 5.7支持JSON字段类型,postgre也是如此。这打破了关系数据库设计的规则。取决于你存储的数据以及你将如何查询 - 然后上面提到的实现**可能完全没问题。为了加入和增加不必要的复杂性,没有意义添加联接。例如如果表格很小。而且,有时候,不完全正常化可能更有效。 – Gravy

我找到了解决方案

$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> 
} 

希望这有助于一些你:)

尝试使用Like语句,例如:

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

正如马特说,使用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(); 
+0

还应该重新设计数据库的结构,这样就不会将游戏名称存储在一个由“,”隔开的列中。 – Hossam

+0

“以”更好“,可扩展和不安全的方式”你的意思是? –

你可以使用正则表达式?例如,如果您想要包含game4或game2的所有行,则可以使用以下命令:

select * FROM users where games REGEXP '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 .';