SQL:笛卡儿积+加入+展平

时间:2015-10-21 14:58:18

标签: mysql sql

在MYSQL 5.6下,我有以下两个表:

CREATE TABLE User
(
    id        INTEGER,
    login     VARCHAR(32),
    isservice BOOLEAN
);

CREATE TABLE Certificate
(
    userid        INTEGER,
    serviceid     INTEGER,
    certificate   VARCHAR(32)
);

使用以下数据:

用户:

id  |  login   |  isservice
---------------------------
1   | john     | false
2   | bob      | false
3   | serviceA | true
4   | serviceB | true

证书:(示例数据,证书列中的实际数据未知

userid | serviceid | Certificale
---------------------------
1      | 3         | Alpha
1      | 4         | Bravo

我创建了以下SQLFiddle:http://sqlfiddle.com/#!9/719a8/2

我正在搜索能够提供以下内容的请求(非存储过程):

id | login | certif_serviceA | certif_serviceB
-----------------------------------------------
1  | john  | Alpha           | Bravo
2  | bob   | NULL            | NULL

到目前为止,我已经尝试过根据我的要求:

SELECT  user.id, user.login,
        service.login as serviceName
FROM User, User as service WHERE service.isservice=1 AND user.isservice=0

但我被困在那里:s

2 个答案:

答案 0 :(得分:2)

正如我已经评论过,你肯定应该重新设计你的数据库。

你要求的是pivot table使用mysql实现起来并不容易。您可以阅读here

但我有这种方法:

http://sqlfiddle.com/#!9/4dc0b2/1

SELECT  user.id, user.login,
    GROUP_CONCAT(Services.login) as ServicesName,
    GROUP_CONCAT(certificate.certificate) as Certificates
FROM User
LEFT JOIN Certificate
ON Certificate.userid = User.id
LEFT JOIN User Services
ON Certificate.serviceid = Services.id
WHERE NOT User.isservice
GROUP BY User.id

SELECT  user.id, user.login,
    GROUP_CONCAT(CONCAT(Services.login,':',certificate.certificate)) as ServicesName
FROM User
LEFT JOIN Certificate
ON Certificate.userid = User.id
LEFT JOIN User Services
ON Certificate.serviceid = Services.id
WHERE NOT User.isservice
GROUP BY User.id

对于目前的情况,你可以接受它。

<强>更新

SELECT  user.id, user.login,
    GROUP_CONCAT(Services.login) as ServicesName,
    GROUP_CONCAT(certificate.certificate) as Certificates
FROM User
LEFT JOIN User Services
ON Services.isservice
LEFT JOIN Certificate
ON Certificate.userid = User.id
  AND Certificate.serviceid = Services.id
WHERE NOT User.isservice
GROUP BY User.id

http://sqlfiddle.com/#!9/1c062/4

答案 1 :(得分:1)

这有效:

SELECT id,
       login,
       MIN(Certificate.certificate) AS certif_serviceA,
       MAX(Certificate.certificate) AS certif_serviceB
FROM USER
LEFT JOIN Certificate ON USER.id = Certificate.userid
WHERE isservice = 0
GROUP BY USER.id