将具有不同值的两行连接在一行中

Posted

技术标签:

【中文标题】将具有不同值的两行连接在一行中【英文标题】:join two rows with different values in a single row 【发布时间】:2019-09-02 09:58:21 【问题描述】:

在一行中获取两条记录

尝试了子句 group by 却没有得到想要的结果。

我有三个表:direccionpunto_suministror_servicio_punto_suministro

id_direccion         others_fields
     10                   XXX        
     10                   YYY  


id_punto_suministro            id_r_servicio_punto_suministro 
       6                            1   
       7                            2   


id_r_servicio_punto_suministro     id_servicio_gas    id_servicio_luz
 1                                   6                 null   
 2                                  null                7

查询:

SELECT 
    punto_suministro.id_direccion,
CASE WHEN  r_servicio_punto_suministro.id_servicio_gas IS NOT NULL THEN punto_suministro.id_punto_suministro END AS Gas,
CASE WHEN  r_servicio_punto_suministro.id_servicio_luz IS NOT NULL THEN punto_suministro.id_punto_suministro END AS Luz
FROM 
    direccion 
    LEFT JOIN punto_suministro ON direccion.id_direccion = punto_suministro.id_direccion 
    LEFT JOIN r_servicio_punto_suministro ON punto_suministro.id_r_servicio_punto_suministro = r_servicio_punto_suministro.id_r_servicio_punto_suministro  
    LEFT JOIN servicio_gas ON r_servicio_punto_suministro.id_servicio_gas = servicio_gas.id_servicio_gas 
    LEFT JOIN servicio_luz ON r_servicio_punto_suministro.id_servicio_luz = servicio_luz.id_servicio_luz
WHERE direccion.id_direccion = 10;

查询返回两行:

 id_direccion     Gas      Luz
     10           6        null
     10           null     7

我想要一条记录中的结果:

 id_direccion     Gas      Luz
     10           6        7

【问题讨论】:

使用GROUP BYmax() 进行聚合 【参考方案1】:

您可以使用条件聚合。您只需要修改您的查询以使用诸如MAX() 之类的聚合函数包围CASEs(MIN() 也可以完成这项工作),并在末尾添加一个GROUP BY 子句:

SELECT 
    punto_suministro.id_direccion,
    MAX(CASE WHEN  r_servicio_punto_suministro.id_servicio_gas IS NOT NULL THEN punto_suministro.id_punto_suministro END) AS Gas,
    MAX(CASE WHEN  r_servicio_punto_suministro.id_servicio_luz IS NOT NULL THEN punto_suministro.id_punto_suministro END) AS Luz
FROM 
    direccion 
    LEFT JOIN punto_suministro ON direccion.id_direccion = punto_suministro.id_direccion 
    LEFT JOIN r_servicio_punto_suministro ON punto_suministro.id_r_servicio_punto_suministro = r_servicio_punto_suministro.id_r_servicio_punto_suministro  
    LEFT JOIN servicio_gas ON r_servicio_punto_suministro.id_servicio_gas = servicio_gas.id_servicio_gas 
    LEFT JOIN servicio_luz ON r_servicio_punto_suministro.id_servicio_luz = servicio_luz.id_servicio_luz
WHERE direccion.id_direccion = 10
GROUP BY punto_suministro.id_direccion;

【讨论】:

【参考方案2】:

一般来说,使用LEFT JOIN 和聚合,您希望按第一个表中的值进行聚合。

因为您使用的是LEFT JOIN,所以我猜您希望即使WHERE 子句上没有匹配项也希望返回一行。

为确保只有一行,请使用聚合查询 *不带GROUP BY

SELECT MAX(d.id_direccion) as id_direccion,
       MAX(CASE WHEN sps.id_servicio_gas IS NOT NULL THEN ps.id_punto_suministro END) AS Gas,
       MAX(CASE WHEN sps.id_servicio_luz IS NOT NULL THEN ps.id_punto_suministro END) AS Luz
FROM direccion d LEFT JOIN
     punto_suministro ps
     ON d.id_direccion = ps.id_direccion LEFT JOIN
     r_servicio_punto_suministro sps
     ON ps.id_r_servicio_punto_suministro = sps.id_r_servicio_punto_suministro LEFT JOIN 
     servicio_gas sg
     ON sps.id_servicio_gas = sg.id_servicio_gas LEFT JOIN
     servicio_luz sl
     ON spm.id_servicio_luz = sl.id_servicio_luz
WHERE d.id_direccion = 10;

如果你知道10存在于数据中,那么你可以使用GROUP BY d.id_direccion

【讨论】:

【参考方案3】:

感谢您的回答。 我终于用连接修复了它:

SELECT 
direccion.id_direccion,
cups_gas.id_punto_suministro AS Gas,
cups_luz.id_punto_suministro AS Luz
FROM
direccion
    INNER JOIN
(SELECT 
    cups,
        id_direccion,
        punto_suministro.id_punto_suministro,
        atr,
        ca,
        fecha_fin
FROM
    punto_suministro
INNER JOIN r_servicio_punto_suministro ON r_servicio_punto_suministro.id_r_servicio_punto_suministro = punto_suministro.id_r_servicio_punto_suministro
INNER JOIN servicio_gas ON r_servicio_punto_suministro.id_servicio_gas = servicio_gas.id_servicio_gas
INNER JOIN r_contrato_punto_suministro ON punto_suministro.id_punto_suministro = r_contrato_punto_suministro.id_punto_suministro
INNER JOIN contrato ON r_contrato_punto_suministro.id_contrato = contrato.id_contrato
INNER JOIN r_servicio_contrato ON contrato.id_contrato = r_servicio_contrato.id_contrato
INNER JOIN servicio ON r_servicio_contrato.id_servicio = servicio.id_servicio) cups_gas ON direccion.id_direccion = cups_gas.id_direccion
    INNER JOIN
(SELECT 
    cups,
        id_direccion,
        punto_suministro.id_punto_suministro,
        atr,
        ca,
        fecha_fin
FROM
    punto_suministro
INNER JOIN r_servicio_punto_suministro ON r_servicio_punto_suministro.id_r_servicio_punto_suministro = punto_suministro.id_r_servicio_punto_suministro
INNER JOIN servicio_luz ON r_servicio_punto_suministro.id_servicio_luz = servicio_luz.id_servicio_luz
INNER JOIN r_contrato_punto_suministro ON punto_suministro.id_punto_suministro = r_contrato_punto_suministro.id_punto_suministro
INNER JOIN contrato ON r_contrato_punto_suministro.id_contrato = contrato.id_contrato
INNER JOIN r_servicio_contrato ON contrato.id_contrato = r_servicio_contrato.id_contrato
INNER JOIN servicio ON r_servicio_contrato.id_servicio = servicio.id_servicio) cups_luz ON direccion.id_direccion = cups_luz.id_direccion
WHERE
direccion.id_direccion = 10;

最好的尊重。

【讨论】:

以上是关于将具有不同值的两行连接在一行中的主要内容,如果未能解决你的问题,请参考以下文章

按具有 2 个不同值的两行数据汇总/分组

Django:显示不同值的对象属性

连接后,表中的两行在另一个表中显示为两个不同的列

聚合具有特定值的两行之间的行

如何基于每个数据框中具有不同名称的两列将两个数据框与 dplyr 连接起来? [复制]

如何在第一行创建具有不同起始值的二维数组? [关闭]