[英]Joining Four Tables without Duplicates From Right Tables in Mysql?
I have to fetch data of all users from database, the database structure is as following, which is just few columns from each table, but enough for proof of concept我必须从数据库中获取所有用户的数据,数据库结构如下,每个表中只有几列,但足以证明概念
CREATE TABLE `tblpersonal` (
`intCompNo` int(11) NOT NULL,
`strName` varchar(500) COLLATE utf8_bin NOT NULL)
CREATE TABLE `tbledu` (
`intEduId` int(11) NOT NULL AUTO_INCREMENT,
`intCompNo` int(11) NOT NULL,
`intEduType` varchar(64) COLLATE utf8_bin DEFAULT NULL)
CREATE TABLE `tbltrain` (
`intTrainId` int(5) NOT NULL AUTO_INCREMENT,
`intCompNo` int(5) NOT NULL,
`strCourseName` varchar(300) COLLATE utf8_bin NOT NULL)
CREATE TABLE `tblrequests` (
`intReqId` int(11) NOT NULL AUTO_INCREMENT,
`intCompNo` int(11) NOT NULL,
`strNotes` varchar(512) COLLATE utf8_bin NOT NULL,
`dateOfSubmit` datetime NOT NULL,
PRIMARY KEY (`intReqId`))
now I am running the query below to get the person name, IDs of his education and ID's of his training, and the last request number he has sent现在我正在运行下面的查询来获取人名、他的教育 ID 和他的培训 ID,以及他发送的最后一个请求编号
SELECT tblpersonal.intCompNo, tblpersonal.strName, tbltrain.intTrainId, tbledu.intEduId, tblrequests.intReqId
FROM tblpersonal
LEFT JOIN tblrequests ON tblpersonal.intCompNo = tblrequests.intCompNo
AND tblrequests.intReqId = (SELECT MAX(req.intReqId) FROM tblrequests AS req WHERE req.intCompNo = tblpersonal.intCompNo)
LEFT JOIN tbltrain ON tblpersonal.intCompNo = tbltrain.intCompNo
LEFT JOIN tbledu ON tblpersonal.intCompNo = tbledu.intCompNo
WHERE tblrequests.intReqId IS NOT NULL
AND tblpersonal.intCompNo = 12368
GROUP BY tblpersonal.intCompNo, tbltrain.intTrainId, tbledu.intEduId
ORDER BY tblpersonal.intCompNo, tbledu.intEduId, tbltrain.intTrainid;
the problem is that I have Cartesian product as a result, shows result for only one employee as below问题是我有笛卡尔积,结果显示只有一名员工的结果如下
+-----------+--------------------------+------------+----------+----------+
| intCompNo | strName | intTrainId | intEduId | intReqId |
+-----------+--------------------------+------------+----------+----------+
| 12368 | ????? ???? ???? ???????? | 5194 | 107 | 388 |
| 12368 | ????? ???? ???? ???????? | 5203 | 107 | 388 |
| 12368 | ????? ???? ???? ???????? | 5575 | 107 | 388 |
| 12368 | ????? ???? ???? ???????? | 5580 | 107 | 388 |
| 12368 | ????? ???? ???? ???????? | 5585 | 107 | 388 |
| 12368 | ????? ???? ???? ???????? | 5591 | 107 | 388 |
| 12368 | ????? ???? ???? ???????? | 5636 | 107 | 388 |
| 12368 | ????? ???? ???? ???????? | 5666 | 107 | 388 |
| 12368 | ????? ???? ???? ???????? | 5676 | 107 | 388 |
How can I get employee data with all his training and education without duplicates如何在没有重复的情况下获得所有培训和教育的员工数据
Running Example of Database can be found below 可以在下面找到数据库的运行示例
If you don't mind a bit of string aggregation如果你不介意一些字符串聚合
SELECT
tblpersonal.intCompNo
,tblpersonal.strName
,GROUP_CONCAT(DISTINCT tblrequests.intReqId ORDER BY tblrequests.intReqId SEPARATOR ', ') AS intReqIdList
,GROUP_CONCAT(DISTINCT tbledu.intEduId ORDER BY tbledu.intEduId SEPARATOR ', ') AS intEduIdList
,GROUP_CONCAT(DISTINCT tbltrain.intTrainId ORDER BY tbltrain.intTrainId SEPARATOR ', ') AS intTrainIdList
,COUNT(DISTINCT tbltrain.intTrainId) AS intTrainIds
FROM tblpersonal
INNER JOIN tblrequests
ON tblrequests.intCompNo = tblpersonal.intCompNo
AND tblrequests.intReqId = (SELECT MAX(req.intReqId) FROM tblrequests AS req WHERE req.intCompNo = tblpersonal.intCompNo)
LEFT JOIN tbltrain
ON tbltrain.intCompNo = tblpersonal.intCompNo
LEFT JOIN tbledu
ON tbledu.intCompNo = tblpersonal.intCompNo
WHERE tblpersonal.intCompNo = 12368
GROUP BY
tblpersonal.intCompNo
,tblpersonal.strName
ORDER BY tblpersonal.intCompNo;
Result:结果:
\nintCompNo | intCompNo | strName |字符串名称 | intReqIdList | intReqIdList | intEduIdList | intEduIdList | intTrainIdList | intTrainIdList | intTrainIds内部列车 ID\n--------: | --------: | :-------- | :-------- | :----------- | :----------- | :----------- | :----------- | :--------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------- -------------------------------------------------- ------------------------------------------ | ----------: ----------:\n 12368 | 12368 | TEST_USER | TEST_USER | 213 |第213话107, 109 | 107, 109 | 5194, 5203, 5575, 5580, 5585, 5591, 5636, 5666, 5676, 5680, 5682, 5685, 5688, 5694, 5700, 5704, 5709, 5713, 5718, 5720, 5722, 5725, 7008, 7014 | 5194, 5203, 5575, 5580, 5585, 5591, 5636, 5666, 5676, 5680, 5682, 5685, 5688, 5694, 5700, 5709, 5, 7, 5, 7, 5, 7, 50, 7, 5, 7, 50, 7, 5, 5, 5 24 24\n
A test on db<>fiddle here对db<>fiddle 的测试在这里
Or how do you feel about uniting them?或者你对联合他们有什么看法?
SET @CompNo = 12368;
SELECT
person.intCompNo
,person.strName AS PersonName
,Src.Source
,Src.SrcId
FROM
(
SELECT req.intCompNo, 'req' AS Source, MAX(req.intReqId) AS SrcId
FROM tblrequests req
WHERE req.intCompNo = @CompNo
GROUP BY req.intCompNo
UNION ALL
SELECT train.intCompNo, 'trn', train.intTrainId
FROM tbltrain AS train
WHERE train.intCompNo = @CompNo
UNION ALL
SELECT edu.intCompNo, 'edu', edu.intEduId
FROM tbledu AS edu
WHERE edu.intCompNo = @CompNo
) AS Src
INNER JOIN tblpersonal AS person
ON Src.intCompNo = person.intCompNo
ORDER BY
person.intCompNo,
Src.Source,
Src.SrcId;
Or maybe this variation of using unions?或者也许是使用联合的这种变体?
SET @CompNo = 12368;
SELECT
person.intCompNo
,person.strName AS PersonName
,Src.intReqId
,Src.intTrainId
,Src.intEduId
FROM
(
SELECT req.intCompNo
, MAX(req.intReqId) AS intReqId
, 0 AS intTrainId
, 0 AS intEduId
FROM tblrequests req
WHERE req.intCompNo = @CompNo
GROUP BY req.intCompNo
UNION ALL
SELECT train.intCompNo
, 0 AS intReqId
, train.intTrainId
, 0 AS intEduId
FROM tbltrain AS train
WHERE train.intCompNo = @CompNo
UNION ALL
SELECT edu.intCompNo
, 0 AS intReqId
, 0 AS intTrainId
, edu.intEduId
FROM tbledu AS edu
WHERE edu.intCompNo = @CompNo
) AS Src
INNER JOIN tblpersonal AS person
ON Src.intCompNo = person.intCompNo
ORDER BY
person.intCompNo,
Src.intTrainId, Src.intEduId, Src.intReqId;
But perhaps you're more looking for a solution like this one that works in MySql 8.0 .但是,也许您更希望找到一种适用于 MySql 8.0 的解决方案。 It re-uses a CTE (Common Table Expression).它重用了 CTE(通用表表达式)。
And uses the window function ROW_NUMBER.并使用窗口函数 ROW_NUMBER。
Basically, it links the edu & requests on the same calculated row number of the bigger training table.基本上,它在更大的训练表的相同计算行号上链接 edu 和请求。
WITH PERSONAL AS
(
SELECT intCompNo, strName
FROM tblpersonal
WHERE intCompNo IN (12368)
)
SELECT
person.intCompNo
,person.strName AS PersonName
,req.intReqId
,edu.intEduId
,trn.intTrainId
FROM PERSONAL AS person
LEFT JOIN
(
SELECT t.intCompNo, t.intTrainId
, ROW_NUMBER()
OVER (PARTITION BY t.intCompNo
ORDER BY t.intTrainId) AS rn
FROM tbltrain AS t
JOIN PERSONAL p
ON p.intCompNo = t.intCompNo
) AS trn
ON trn.intCompNo = person.intCompNo
LEFT JOIN
(
SELECT t.intCompNo
, MAX(t.intReqId) AS intReqId
, 1 AS rn
FROM tblrequests t
JOIN PERSONAL p
ON p.intCompNo = t.intCompNo
GROUP BY t.intCompNo
) AS req
ON req.intCompNo = trn.intCompNo
AND req.rn = trn.rn
LEFT JOIN
(
SELECT t.intCompNo, t.intEduId
, ROW_NUMBER()
OVER (PARTITION BY t.intCompNo
ORDER BY t.intEduId) AS rn
FROM tbledu AS t
JOIN PERSONAL p
ON p.intCompNo = p.intCompNo
) AS edu
ON edu.intCompNo = trn.intCompNo
AND edu.rn = trn.rn
ORDER BY person.intCompNo;
\nintCompNo | intCompNo | PersonName |人名 | intReqId |请求 ID | intEduId |国际化 | intTrainId内部列车ID\n--------: | --------: | :--------- | :--------- | -------: | -------: | -------: | -------: | ---------: ---------:\n 12368 | 12368 | TEST_USER | TEST_USER | 213 |第213话107 | 107 | 5194 5194\n 12368 | 12368 | TEST_USER | TEST_USER | null |空| 109 | 109 | 5203 5203\n 12368 | 12368 | TEST_USER | TEST_USER | null |空| null |空| 5575 5575\n 12368 | 12368 | TEST_USER | TEST_USER | null |空| null |空| 5580 5580\n 12368 | 12368 | TEST_USER | TEST_USER | null |空| null |空| 5585 5585\n ... ...\n\n
You seem to be after something like this, which, if not correct, at least has the appearance of a valid query.你似乎在追求这样的事情,如果不正确,至少看起来是一个有效的查询。
SELECT DISTINCT p.intCompNo
, p.strName
, t.intTrainId
, e.intEduId
, r.intReqId
FROM tblpersonal p
LEFT
JOIN tblrequests r
ON r.intCompNo = p.intCompNo
JOIN
( SELECT req.intCompNo
, MAX(req.intReqId) intreqid
FROM tblrequests req
GROUP
BY req.intCompNo
) x
ON x.intreqid = r.intReqId
AND x.intCompNo = p.intCompNo)
LEFT
JOIN tbltrain t
ON t.intCompNo = p.intCompNo
LEFT
JOIN tbledu e
ON e.intCompNo = p.intCompNo
WHERE r.intReqId IS NOT NULL
AND p.intCompNo = 12368
ORDER
BY p.intCompNo
, e.intEduId
, t.intTrainid;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.