PHP PDO可能的LEFT JOIN获取列名和列值

时间:2016-10-11 10:32:31

标签: php pdo left-join

我有两张桌子:

  1. 用户

    标准用户表(身份证,姓名,电子邮件,国家,城市,密码,性别)。

  2. 语言

    每列都有一个语言的名称,例如“英语”,“西班牙语”,“俄语”。 任何列的值都是int,表示相应语言的熟练程度。

  3. 每行的ID都从用户表user.id中删除,以保存用户的语言。标准条目为NULL,如果用户说出语言,则将替换为int。

    我想选择所有符合搜索查询条目(国家/地区,城市,性别)的用户,然后我想根据用户表LEFT JOIN languages ON (user.id=languages.id)中的用户ID检查语言表,并仅返回列名称和不包含NULL的列的值。

    到目前为止我的方法:

    sql = 'SELECT * FROM ' . self::TABLE . 
          ' WHERE country=? AND city LIKE ? AND gender LIKE ? LEFT JOIN languages ON ('.  
           self::TABLE .
          '.id=languages.id) SHOW COLUMNS WHERE COLUMN NAME ? ORDER BY name DESC';
    

    上面的代码显然是错误的,我的问题是,在SHOW COLUMNS之后我将如何解决这个问题?

    样本记录: 语言表 user_id = 9,英语= NULL,西班牙语= 3,俄语= 2,韩语= 1

    用户表 id = 9,email = me @ me.com,country =韩国,city = Seoul,gender = 1

    在我仅选择符合搜索查询提供的国家/地区,城市和性别的用户后,我想获取每个用户ID并检查语言表中是否包含非空的列,并将这些列名称与单独为每个用户的用户对象赋值,然后返回所有对象,这样我就可以将它们输出给正在进行搜索的登录用户。

    我如何插入和更新语言:

    public function updateLanguages($languages, $id) {
    
        $sql = "SELECT user_id FROM " . self::TABLE . " WHERE user_id=? LIMIT 1";
        $stmt = $this->dbh->prepare($sql);
        $stmt->execute(array($id));
        $userId = $stmt->fetchAll();
    
        if (empty($userId)) {
    
            $sql = 'INSERT INTO ' . self::TABLE . ' (user_id) VALUES(?)';
            $values = array($id);
            $stmt = $this->dbh->prepare($sql);
            $stmt->execute($values);
    
            $this->resetLanguages($id);
    
            for ($i = 0; $i < count($languages) / 2; $i++) {
    
                $sql = 'UPDATE ' . self::TABLE . ' SET ' . $languages['language' . $i] . '=? WHERE user_id =? LIMIT 1';
                $stmt = $this->dbh->prepare($sql);
                $stmt->execute(array($languages['langlevel' . $i], $id));
                $stmt = null;
            }
        } else {
    
            $this->resetLanguages($id);
    
            for ($i = 0; $i < count($languages) / 2; $i++) {
    
                $sql = 'UPDATE ' . self::TABLE . ' SET ' . $languages['language' . $i] . '=? WHERE user_id =? LIMIT 1';
                $stmt = $this->dbh->prepare($sql);
                $stmt->execute(array($languages['langlevel' . $i], $id));
                $stmt = null;
            }
        }
    }
    

    重置功能:

    public function resetLanguages($id) {
        $languages = new Languages();
        $allLangs = $this->getLanguages();
        $allLangs = array_slice($allLangs, 1, 137);
    
        foreach ($allLangs as $lang) {
    
            $sql = 'UPDATE ' . self::TABLE . ' SET ' . $lang['Field'] . '=? WHERE user_id =? LIMIT 1';
            $stmt = $this->dbh->prepare($sql);
            $stmt->execute(array(null, $id));
            $stmt = null;
        }
    }
    

    用户插入:

    public function save($data) {
        $utilityManager = new UtilityManager();
        $rand = $utilityManager->randomGen();
        $user = new User();
        $user->arrayToObject($data);
        $folderName = $user->getName() . $rand;
        $profileFolder = 'profilePic';
        mkdir('users/' . $folderName, 0755);
        mkdir("users/$folderName/" . $profileFolder, 0755);
        $sql = 'INSERT INTO ' . self::TABLE . ' (name, email, country, password, emailConfirm, imageFolder, registered, lastOnline) VALUES(?, ?, ?, ?, ?, ?, NOW(), NOW())';
        $values = array($user->getName(), $user->getEmail(), $user->getCountry(), $user->getPassword(), $user->getEmailConfirm(), $folderName);
        $stmt = $this->dbh->prepare($sql); // prepares the sql statement to be filled
        $stmt->execute($values); //fills the sql statement with the $values array
    
        if ($stmt->rowCount() > 0) {
            $utilityManager->sendEmail(array('reg', $user->getEmail(), $user->getName(), $user->getEmailConfirm()));
        }
    }
    

1 个答案:

答案 0 :(得分:-1)

您的数据库设计错误。 languages表应该只有两列:user_id和language_id

在这种情况下,您只需将用户表连接到语言表

即可
SELECT * FROM users u, languages l  
    WHERE u.id = user_id AND lang_id=? AND country=? AND city LIKE ? AND gender LIKE ? 

请注意,通过适当的结构,您将获得很多优势。例如,您可以添加“熟练度”字段来标记不同的渐变,而不是仅对该语言使用“是”或“否”。然后选择所选语言的熟练程度不低于给定语言的所有用户。