3

我有两张表,一张是候选人和他们的技能,另一张是工作和工作所需的技能,如下图所示:

CSID = 候选人技能 ID (PK)
CID = 候选人 ID (FK)
S_CODE = 技能代码 (FK)

这是候选技能表

+------------+---------+---------+
| CSID       | CID     |  S_CODE |
+------------+---------+---------+
| 1          | 1       | 5       |
| 2          | 1       | 9       |
| 3          | 2       | 5       |
| 4          | 2       | 10      |
+------------+---------+---------+

SJID = 技能作业 ID (PK)
JID = 作业 ID (FK)
S_CODE = 技能代码 (FK)

这是 Skill_job 表:

+------------+---------+---------+
| SJID       | JID     |  S_CODE |
+------------+---------+---------+
| 12         | 50      | 5       |
| 13         | 50      | 9       |
| 14         | 51      | 1       |
| 15         | 52      | 10      |
+------------+---------+---------+

因此,在此示例中,职位 50 的唯一候选人将是 1,因为两者的技能代码 (S_CODE) 都是 5 和 9,但我也希望候选人 2 与 52 匹配,因为它具有所需的工作技能和一个额外的。我尝试了几种方法来匹配工作和候选人,但我失败了,这种方法的一个例子是下面的代码:

    SELECT * , COUNT(skill_job.S_CODE) AS cnt FROM candidate_skill,
 skill_job WHERE candidate_skill.S_CODE = skill_job.S_CODE HAVING (cnt >=2)

问题是,这只将找到的候选人限制为一个,如果我删除 COUNT 子句,它会列出所有仅与一项技能匹配的候选人,因此候选人 2 也将与工作 50 匹配。

这是来自 phpmyadmin 的表的 mysql 代码:

    -- phpMyAdmin SQL Dump
-- version 3.4.5
-- http://www.phpmyadmin.net
--
-- Host: localhost
-- Generation Time: Jul 16, 2012 at 09:27 PM
-- Server version: 5.5.16
-- PHP Version: 5.3.8

SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";


/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;

--
-- Database: `employment`
--

-- --------------------------------------------------------

--
-- Table structure for table `candidate`
--

CREATE TABLE IF NOT EXISTS `candidate` (
  `CID` int(4) NOT NULL AUTO_INCREMENT,
  `title` varchar(5) NOT NULL,
  `fname` varchar(30) NOT NULL,
  `lname` varchar(30) NOT NULL,
  `dob` date NOT NULL,
  `email` varchar(50) NOT NULL,
  `address` varchar(255) NOT NULL,
  `city` varchar(50) NOT NULL,
  `postcode` varchar(10) NOT NULL,
  `phone_num` varchar(11) NOT NULL,
  `username` varchar(40) NOT NULL,
  `password` varchar(40) NOT NULL,
  `regdate` datetime NOT NULL,
  `acc_type` enum('c','s') NOT NULL DEFAULT 'c',
  `emailactivate` enum('0','1') NOT NULL DEFAULT '0',
  `cv_name` varchar(60) NOT NULL,
  `cv` blob NOT NULL,
  PRIMARY KEY (`CID`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 COMMENT='// this is the table for the candidates' AUTO_INCREMENT=175 ;

--
-- Dumping data for table `candidate`
--

INSERT INTO `candidate` (`CID`, `title`, `fname`, `lname`, `dob`, `email`, `address`, `city`, `postcode`, `phone_num`, `username`, `password`, `regdate`, `acc_type`, `emailactivate`, `cv_name`, `cv`) VALUES
(128, 'Mr', 'clement', 'Chilingulo', '0000-00-00', 'chlngl@yahoo.com', '28 oakfield Road', 'london', 'E6 1LW', '07771611873', 'casante', 'b59c67bf196a4758191e42f76670ceba', '0000-00-00 00:00:00', 'c', '0', '', '');
INSERT INTO `candidate` (`CID`, `title`, `fname`, `lname`, `dob`, `email`, `address`, `city`, `postcode`, `phone_num`, `username`, `password`, `regdate`, `acc_type`, `emailactivate`, `cv_name`, `cv`) VALUES
(134, 'Mr', 'rverv', 'revrb', '0000-00-00', 'tdbsdrt', 'trsbrtd', 'trbtrtrb', 'tbrfbgrts', 'trfbtrgbrfg', 'clement', 'b59c67bf196a4758191e42f76670ceba', '0000-00-00 00:00:00', 's', '0', '', '');
INSERT INTO `candidate` (`CID`, `title`, `fname`, `lname`, `dob`, `email`, `address`, `city`, `postcode`, `phone_num`, `username`, `password`, `regdate`, `acc_type`, `emailactivate`, `cv_name`, `cv`) VALUES
(165, 'Mr', 'oinInINOioni', 'ioin', '0000-00-00', 'inioimn', 'in', 'oin', 'oni', 'io', 'k', '7b8b965ad4bca0e41ab51de7b31363a1', '0000-00-00 00:00:00', 'c', '0', '', ''),
(166, 'Mr', 'pjINoNlkinoinoi', 'ino', '0000-00-00', 'oimpnponi', 'inoi', 'no', 'nj', 'nio', 'nio', 'eb5bc837d01b911029ae378e8a1c9f5d', '0000-00-00 00:00:00', 'c', '0', '', ''),
(167, 'Mr', 'vrae', 'ergvaer', '0000-00-00', 'aerbg', 'aergvera', 'aergvrea', 'aergvear', 'aergarev', 'grebvarvf', '609c1b136ec8d0d2dfdf9a2105fb605f', '0000-00-00 00:00:00', 'c', '0', '', ''),
(168, 'Mr', 'vrae', 'ergvaer', '0000-00-00', 'aerbg', 'aergvera', 'aergvrea', 'aergvear', 'aergarev', 'grebvarvf', '609c1b136ec8d0d2dfdf9a2105fb605f', '0000-00-00 00:00:00', 'c', '0', '', ''),
(169, 'Mr', 'ubp', 'bu', '0000-00-00', 'ubip', ';ub', 'ubi', 'ubo', 'buo', 'ubiipbu', '9f44ce1389a3e7372834ed730b559a5e', '0000-00-00 00:00:00', 'c', '0', '', ''),
(170, 'Mr', 'rvev', 'ferhbgetb', '0000-00-00', 'tsbtrb', 'trbstrb', 'trbsfb ', 'stb stb', 'vvfs', 'csdcdsvarewdcv', 'd41d8cd98f00b204e9800998ecf8427e', '0000-00-00 00:00:00', 'c', '0', '', ''),
(171, 'Mr', 'rvev', 'ferhbgetb', '0000-00-00', 'tsbtrb', 'trbstrb', 'trbsfb ', 'stb stb', 'vvfs', 'csdcdsvarewdcv', 'd41d8cd98f00b204e9800998ecf8427e', '0000-00-00 00:00:00', 'c', '0', '', ''),
(172, '', '', '', '0000-00-00', '', '', '', '', '', '', 'd41d8cd98f00b204e9800998ecf8427e', '0000-00-00 00:00:00', 'c', '0', '', ''),
(173, '', 'dds', 'vrv av', '0000-00-00', 'rvear', 'vreverav', 'rvedfsdv', 'frvdvf', 'fveavd', 'vdrareavdv', '84c71ac76340092398a1ed4bc7d6fe19', '0000-00-00 00:00:00', 'c', '0', '', ''),
(174, '', 'dds', 'vrv av', '0000-00-00', 'rvedwear', 'vreverav', 'rvedfsdv', 'frvdvf', 'fveavd', 'vdraredfcavdv', 'd41d8cd98f00b204e9800998ecf8427e', '0000-00-00 00:00:00', 'c', '0', '', '');

-- --------------------------------------------------------

--
-- Table structure for table `candidate_skill`
--

CREATE TABLE IF NOT EXISTS `candidate_skill` (
  `CSID` int(4) NOT NULL AUTO_INCREMENT,
  `CID` int(4) NOT NULL,
  `S_CODE` int(4) NOT NULL,
  PRIMARY KEY (`CSID`),
  KEY `CID` (`CID`),
  KEY `S_CODE` (`S_CODE`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 COMMENT='//match candidate and skill' AUTO_INCREMENT=131 ;

--
-- Dumping data for table `candidate_skill`
--

INSERT INTO `candidate_skill` (`CSID`, `CID`, `S_CODE`) VALUES
(114, 134, 2),
(116, 134, 9),
(121, 134, 5),
(126, 128, 1);

-- --------------------------------------------------------

--
-- Table structure for table `job`
--

CREATE TABLE IF NOT EXISTS `job` (
  `JID` int(4) NOT NULL AUTO_INCREMENT,
  `job_title` varchar(40) NOT NULL,
  `job_desc` varchar(255) NOT NULL,
  `start_date` date NOT NULL,
  `end_date` date NOT NULL,
  PRIMARY KEY (`JID`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 COMMENT='// this is the table for the job vacancies' AUTO_INCREMENT=10 ;

--
-- Dumping data for table `job`
--

INSERT INTO `job` (`JID`, `job_title`, `job_desc`, `start_date`, `end_date`) VALUES
(1, 'engineer', ' fix engineering ish that is messed ', '0000-00-00', '0000-00-00'),
(5, 'pilot', '', '0000-00-00', '0000-00-00'),
(8, 'Charity Helper', ' ', '0000-00-00', '0000-00-00'),
(9, 'accountant', '  ', '0000-00-00', '0000-00-00');

-- --------------------------------------------------------

--
-- Table structure for table `skill`
--

CREATE TABLE IF NOT EXISTS `skill` (
  `S_CODE` int(4) NOT NULL AUTO_INCREMENT COMMENT '// this is the skill primary key',
  `skill_name` varchar(40) NOT NULL,
  `skill_desc` varchar(255) NOT NULL,
  PRIMARY KEY (`S_CODE`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=11 ;

--
-- Dumping data for table `skill`
--

INSERT INTO `skill` (`S_CODE`, `skill_name`, `skill_desc`) VALUES
(1, 'speaking', 'English is your first language'),
(2, '  writing', 'You can write English very well'),
(3, ' public', ''),
(5, 'initiative', ''),
(6, 'interviewing', ''),
(7, 'negotiating', ''),
(8, 'leading', ''),
(9, '  energy', ''),
(10, ' organisation', '');

-- --------------------------------------------------------

--
-- Table structure for table `skill_job`
--

CREATE TABLE IF NOT EXISTS `skill_job` (
  `SJID` int(4) NOT NULL AUTO_INCREMENT,
  `JID` int(4) NOT NULL,
  `S_CODE` int(4) NOT NULL,
  PRIMARY KEY (`SJID`),
  KEY `S_CODE` (`S_CODE`),
  KEY `JID` (`JID`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=106 ;

--
-- Dumping data for table `skill_job`
--

INSERT INTO `skill_job` (`SJID`, `JID`, `S_CODE`) VALUES
(91, 5, 2),
(94, 5, 5),
(95, 5, 9),
(98, 1, 1),
(102, 1, 8),
(105, 8, 8);

--
-- Constraints for dumped tables
--

--
-- Constraints for table `candidate_skill`
--
ALTER TABLE `candidate_skill`
  ADD CONSTRAINT `candidate_skill_ibfk_3` FOREIGN KEY (`CID`) REFERENCES `candidate` (`CID`) ON DELETE CASCADE ON UPDATE CASCADE,
  ADD CONSTRAINT `candidate_skill_ibfk_4` FOREIGN KEY (`S_CODE`) REFERENCES `skill` (`S_CODE`) ON DELETE CASCADE ON UPDATE CASCADE;

--
-- Constraints for table `skill_job`
--
ALTER TABLE `skill_job`
  ADD CONSTRAINT `skill_job_ibfk_4` FOREIGN KEY (`JID`) REFERENCES `job` (`JID`) ON DELETE CASCADE ON UPDATE CASCADE,
  ADD CONSTRAINT `skill_job_ibfk_5` FOREIGN KEY (`S_CODE`) REFERENCES `skill` (`S_CODE`) ON DELETE CASCADE ON UPDATE CASCADE;

/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
4

5 回答 5

4

双重否定是你的朋友(虽然我对 MySQL 的了解还不足以判断它是否支持它):

SELECT DISTINCT CS.CID, SJ.JID
FROM CANDIDATE_SKILL CS
JOIN SKILL_JOB SJ ON CS.S_CODE = SJ.S_CODE
WHERE NOT EXISTS(SELECT 1
                 FROM SKILL_JOB SJ2
                 WHERE SJ.JID = SJ2.JID
                   AND NOT EXISTS(SELECT 1
                                  FROM CANDIDATE_SKILL CS2
                                  WHERE CS.CID = CS2.CID
                                    AND SJ2.S_CODE = CS2.S_CODE))

对此的“人工翻译”是说不应该存在候选人不具备的工作所需的任何技能。

于 2012-07-16T19:31:53.573 回答
1

似乎您需要使用INNER JOIN来组合您的两个表,然后比较它们的行值。

于 2012-07-16T19:11:47.990 回答
0

应该是这样的。。

SELECT
   CID
FROM 
   candidate_skill
WHERE
   S_CODE IN (
               SELECT S_CODE FROM skill_jobs where JID = 52 
             )
GROUP BY CID

更正:先前的查询将无法匹配所有必需的 S_CODE

SELECT
   CID, COUNT(CSID) as cnt
FROM 
   candidate_skill
INNER JOIN skill_jobs 
WHERE
   S_CODE IN (
               SELECT S_CODE FROM skill_jobs where JID = 52 
             )
GROUP BY CID 
HAVING cnt = (
               SELECT count(*) from skill_jobs where JID = 52
             )
于 2012-07-16T19:18:17.147 回答
0

您将需要更复杂的 JOIN,而且我认为没有简单的方法可以同时回答您的请求和显而易见的请求“候选人 X 与工作 Y 的匹配度如何?” 和“候选人 X 适合工作 Y 多少?”。

不管怎样,就到这里吧。

SELECT candidate_skill.CID, skill_job.JID, COUNT(*) AS has, sjtot.needed
    FROM skill_job JOIN candidate_skill ON (candidate_skill.S_CODE = skill_job.S_CODE)
    LEFT JOIN ( SELECT JID, COUNT(*) AS needed FROM skill_job GROUP BY JID ) AS sjtot
        ON ( skill_job.JID = sjtot.JID )
GROUP BY CID, JID
HAVING has >= needed;

在实践中,我首先将所需技能分组到 Skill_job 上,这告诉我工作 50 需要两个技能。

有了这个,我 LEFT JOIN 要求和候选人技能;有些候选人会加入所有技能,有些则不会。然后只需计算匹配的数量即可。

+------+------+-----+--------+
| CID  | JID  | has | needed |
+------+------+-----+--------+
|    1 |   50 |   2 |      2 |
|    2 |   52 |   1 |      1 |
+------+------+-----+--------+

再三考虑,可能会选择所需的技能水平和提供的技能水平,并且 CASE WHEN 用于提取匹配项(如果提供 >= 需要,则为 1,否则提供/需要)。然后可以将结果值的平均值用作“技能匹配”指数。

至于“X如何匹配Y?” 问题,一旦您知道候选人 CID 1 适合 JID 50 的工作,您就可以在候选人和工作之间运行 LEFT JOIN。您已经知道,无论工作要求什么,候选人都具有,但是这样您就可以检索候选人具有哪些未要求的技能,以及其他相关价值。

一个嵌套查询加入上面的查询和最后一个查询可能会一口气告诉你一切,但我认为这将是一个代价高昂的一举:-)

于 2012-07-16T19:38:58.573 回答
0

如果您不关心跨 dbms 支持,您可以使用 mysql 特定的 group_concat 将两个 s_code 集减少为字符串,每个候选人/作业一个,然后像这样比较它们:

select * from 
(select cs.cid, group_concat(cs.s_code order by cs.s_code) skills 
    from candidate_skill cs group by cs.cid) cs, 
(select sj.jid, group_concat(sj.s_code order by sj.s_code) skills 
    from skill_job sj group by sj.jid) sj
where sj.skills = cs.skills

请注意,当您的表增长时,最终 where 会越来越慢,并且您无法在 group_concat() 创建的字段上创建索引。

于 2012-07-16T19:47:28.257 回答