通过减少子查询来优化查询(每个子查询有多个别名,可以吗?)

时间:2018-12-06 19:19:15

标签: mysql

我想减少主查询中的查询数量。由于数据分布在不同的表中,因此我通过与ID进行比较来收集必要的信息。

这是我的功能查询。但是,我认为这对于服务器性能而言应该是非常昂贵的:

SELECT 
    *, 
    (SELECT trtId FROM sistema_trecho treo WHERE treo.treId = voo.vooOrigemId) as trtIdOrigem, 
    (SELECT trtTitulo FROM sistema_trecho_tipo trt WHERE trt.trtId = trtIdOrigem) as trtTituloOrigem, 
    (SELECT treNome FROM sistema_trecho treo WHERE treo.treId = voo.vooOrigemId) as treNomeOrigem, 
    (SELECT treICAO FROM sistema_trecho treo WHERE treo.treId = voo.vooOrigemId) as treICAOOrigem, 
    (SELECT treIATA FROM sistema_trecho treo WHERE treo.treId = voo.vooOrigemId) as treIATAOrigem, 
    (SELECT trtId FROM sistema_trecho tred WHERE tred.treId = voo.vooDestinoId) as trtIdDestino, 
    (SELECT trtTitulo FROM sistema_trecho_tipo trt WHERE trt.trtId = trtIdDestino) as trtTituloDestino, 
    (SELECT treNome FROM sistema_trecho tred WHERE tred.treId = voo.vooDestinoId) as treNomeDestino, 
    (SELECT treICAO FROM sistema_trecho tred WHERE tred.treId = voo.vooDestinoId) as treICAODestino, 
    (SELECT treIATA FROM sistema_trecho tred WHERE tred.treId = voo.vooDestinoId) as treIATADestino,
    (SELECT cidNome FROM sistema_trecho treo LEFT JOIN sistema_cidade cido ON cido.cidId = treo.cidId WHERE treo.treId = voo.vooOrigemId) as treEnderecoCidadeOrigem,
    (SELECT cidAlias FROM sistema_trecho treo LEFT JOIN sistema_cidade cido ON cido.cidId = treo.cidId WHERE treo.treId = voo.vooOrigemId) as treAliasCidadeOrigem,
    (SELECT estUF FROM sistema_trecho treo LEFT JOIN sistema_cidade cido ON cido.cidId = treo.cidId LEFT JOIN sistema_estado est ON est.estId = cido.estId WHERE treo.treId = voo.vooOrigemId) as treEnderecoEstadoOrigem,
    (SELECT cidNome FROM sistema_trecho tred LEFT JOIN sistema_cidade cidd ON cidd.cidId = tred.cidId WHERE tred.treId = voo.vooDestinoId) as treEnderecoCidadeDestino,
    (SELECT cidAlias FROM sistema_trecho tred LEFT JOIN sistema_cidade cidd ON cidd.cidId = tred.cidId WHERE tred.treId = voo.vooDestinoId) as treAliasCidadeDestino,
    (SELECT estUF FROM sistema_trecho tred LEFT JOIN sistema_cidade cidd ON cidd.cidId = tred.cidId LEFT JOIN sistema_estado est ON est.estId = cidd.estId WHERE tred.treId = voo.vooDestinoId) as treEnderecoEstadoDestino

FROM 
    sistema_voo_operadora vop 
    LEFT JOIN sistema_operadora ope ON vop.opeId = ope.opeId 
    LEFT JOIN sistema_voo voo ON vop.vooId = voo.vooId 
    LEFT JOIN sistema_tipo_voo tiv ON voo.tivId = tiv.tivId 
    LEFT JOIN sistema_aeronave aer ON vop.aerId = aer.aerId 
    LEFT JOIN sistema_tipo_aeronave tia ON aer.tiaId = tia.tiaId

WHERE 
    tiv.tivId = 2 
    AND vooAtivo = 'S' 
    AND vooExcluido = 'N' 
    AND opeAtivo = 'S' 
    AND opeExcluido = 'N' 
    AND vopAtivo = 'S' 
    AND vopExcluido = 'N' 

ORDER BY 
    RAND() 

LIMIT 
    0,4;

我至少希望最初的子查询以某种方式进行分组。我尝试了以下操作,但无济于事(返回语法错误):

尝试01:

SELECT 
    *, 
    (SELECT trtId, treNome, treICAO, treIATA FROM sistema_trecho treo WHERE treo.treId = voo.vooOrigemId) as trtIdOrigem, treNomeOrigem, treICAOOrigem, treIATAOrigem 
    (SELECT trtTitulo FROM sistema_trecho_tipo trt WHERE trt.trtId = trtIdOrigem) as trtTituloOrigem, 
    (SELECT trtId, treNome, treICAO, treIATA FROM sistema_trecho tred WHERE tred.treId = voo.vooDestinoId) as trtIdDestino, treNomeDestino, treICAODestino, treIATADestino
    (SELECT trtTitulo FROM sistema_trecho_tipo trt WHERE trt.trtId = trtIdDestino) as trtTituloDestino, 
    (SELECT cidNome FROM sistema_trecho treo LEFT JOIN sistema_cidade cido ON cido.cidId = treo.cidId WHERE treo.treId = voo.vooOrigemId) as treEnderecoCidadeOrigem,
    (SELECT cidAlias FROM sistema_trecho treo LEFT JOIN sistema_cidade cido ON cido.cidId = treo.cidId WHERE treo.treId = voo.vooOrigemId) as treAliasCidadeOrigem,
    (SELECT estUF FROM sistema_trecho treo LEFT JOIN sistema_cidade cido ON cido.cidId = treo.cidId LEFT JOIN sistema_estado est ON est.estId = cido.estId WHERE treo.treId = voo.vooOrigemId) as treEnderecoEstadoOrigem,
    (SELECT cidNome FROM sistema_trecho tred LEFT JOIN sistema_cidade cidd ON cidd.cidId = tred.cidId WHERE tred.treId = voo.vooDestinoId) as treEnderecoCidadeDestino,
    (SELECT cidAlias FROM sistema_trecho tred LEFT JOIN sistema_cidade cidd ON cidd.cidId = tred.cidId WHERE tred.treId = voo.vooDestinoId) as treAliasCidadeDestino,
    (SELECT estUF FROM sistema_trecho tred LEFT JOIN sistema_cidade cidd ON cidd.cidId = tred.cidId LEFT JOIN sistema_estado est ON est.estId = cidd.estId WHERE tred.treId = voo.vooDestinoId) as treEnderecoEstadoDestino

FROM 
    sistema_voo_operadora vop 
    LEFT JOIN sistema_operadora ope ON vop.opeId = ope.opeId 
    LEFT JOIN sistema_voo voo ON vop.vooId = voo.vooId 
    LEFT JOIN sistema_tipo_voo tiv ON voo.tivId = tiv.tivId 
    LEFT JOIN sistema_aeronave aer ON vop.aerId = aer.aerId 
    LEFT JOIN sistema_tipo_aeronave tia ON aer.tiaId = tia.tiaId

WHERE 
    tiv.tivId = 2 
    AND vooAtivo = 'S' 
    AND vooExcluido = 'N' 
    AND opeAtivo = 'S' 
    AND opeExcluido = 'N' 
    AND vopAtivo = 'S' 
    AND vopExcluido = 'N' 

ORDER BY 
    RAND() 

LIMIT 
    0,4;

尝试02:

SELECT 
    *, 
    (SELECT trtId as trtIdOrigem as treNomeOrigem, treNome as treNomeOrigem, treICAO as treICAOOrigem, treIATA as treIATAOrigem FROM sistema_trecho treo WHERE treo.treId = voo.vooOrigemId),
    (SELECT trtId as trtIdDestino, treNome as treNomeDestino, treICAO as treICAODestino, treIATA as treIATADestino FROM sistema_trecho tred WHERE tred.treId = voo.vooDestinoId),
    (SELECT cidNome as treEnderecoCidadeOrigem, cidAlias as treAliasCidadeOrigem, estUF as treEnderecoEstadoOrigem FROM sistema_trecho treo LEFT JOIN sistema_cidade cido ON cido.cidId = treo.cidId LEFT JOIN sistema_estado est ON est.estId = cido.estId WHERE treo.treId = voo.vooOrigemId),
    (SELECT cidNome as treEnderecoCidadeDestino, cidAlias as treAliasCidadeDestino, estUF as treEnderecoEstadoDestino FROM sistema_trecho tred LEFT JOIN sistema_cidade cidd ON cidd.cidId = tred.cidId LEFT JOIN sistema_estado est ON est.estId = cidd.estId WHERE tred.treId = voo.vooDestinoId),
    (SELECT trtTitulo FROM sistema_trecho_tipo trt WHERE trt.trtId = trtIdOrigem) as trtTituloOrigem, 
    (SELECT trtTitulo FROM sistema_trecho_tipo trt WHERE trt.trtId = trtIdDestino) as trtTituloDestino

FROM 
    sistema_voo_operadora vop 
    LEFT JOIN sistema_operadora ope ON vop.opeId = ope.opeId 
    LEFT JOIN sistema_voo voo ON vop.vooId = voo.vooId 
    LEFT JOIN sistema_tipo_voo tiv ON voo.tivId = tiv.tivId 
    LEFT JOIN sistema_aeronave aer ON vop.aerId = aer.aerId 
    LEFT JOIN sistema_tipo_aeronave tia ON aer.tiaId = tia.tiaId

WHERE 
    tiv.tivId = 2 
    AND vooAtivo = 'S' 
    AND vooExcluido = 'N' 
    AND opeAtivo = 'S' 
    AND opeExcluido = 'N' 
    AND vopAtivo = 'S' 
    AND vopExcluido = 'N' 

ORDER BY 
    RAND() 

LIMIT 
    0,4;

我需要从sistema_voo_operadora(vop)表中提取4条记录。

在此里面,我需要带入飞行数据(voo),这些数据位于sistema_voo(voo.vooId = vop.vooId)

在sistema_voo表中,我保存了出发地ID和目的地ID。原始数据在sistema_trecho中(原始为treO,目标为treD)。因为我仍然需要此查询中每个地方的城市,州和州,所以我只能进行子查询。

需要左联接才能带来更多外部信息,例如承运人信息,航班类型,使用的飞机和飞机类型。

我可以在此查询中优化的内容将为我省掉一些头发。

想法?

1 个答案:

答案 0 :(得分:1)

  1. 您不能在SQL的SELECT子句中提供的子查询中浏览多个列。
  2. 这里真的没有理由进行子查询,只需通过联接即可。遵循逻辑将容易得多,并且对数据库的压力也较小。

考虑:

SELECT 
    vop.*, 
    ope.*,
    voo.*,
    tiv.*,
    aer.*,
    tia.*, 
    treo_origem.trtId as trtIdOrigem, 
    treo_origem.trtTitulo as trtTituloOrigem, 
    treo_origem.treNome as treNomeOrigem, 
    treo_origem.treICAO as treICAOOrigem, 
    treo_origem.treIATA as treIATAOrigem, 
    treo_destino.trtId as trtIdDestino, 
    treo_destino.trtTitulo as trtTituloDestino, 
    treo_destino.treNome as treNomeDestino, 
    treo_destino.treICAO as treICAODestino, 
    treo_destino.treIATA as treIATADestino,
    cido_origem.cidNome as treEnderecoCidadeOrigem,
    cido_origem.cidAlias as treAliasCidadeOrigem,
    cido_origem.estUF as treEnderecoEstadoOrigem,
    cido_destino.cidNome  as treEnderecoCidadeDestino,
    cido_destino.cidAlias  as treAliasCidadeDestino,
    cido_destino.estUF  as treEnderecoEstadoDestino

FROM 
    sistema_voo_operadora vop 
    LEFT JOIN sistema_operadora ope ON vop.opeId = ope.opeId 
    LEFT JOIN sistema_voo voo ON vop.vooId = voo.vooId 
    LEFT JOIN sistema_tipo_voo tiv ON voo.tivId = tiv.tivId 
    LEFT JOIN sistema_aeronave aer ON vop.aerId = aer.aerId 
    LEFT JOIN sistema_tipo_aeronave tia ON aer.tiaId = tia.tiaId
    LEFT JOIN sistemo_trecho treo_origem ON treo_origem.treID = voo.vooOrigemId
    LEFT JOIN sistemo_trecho treo_destino ON treo_destino.treId = voo.vooDestinoId
    LEFT JOIN sistema_cidade cido_origem ON cido_origem.cidId = treo_origem.cidId
    LEFT JOIN sistema_cidade cido_destino ON cido_destino.cidID = treo_destino.cidID

WHERE 
    tiv.tivId = 2 
    AND vooAtivo = 'S' 
    AND vooExcluido = 'N' 
    AND opeAtivo = 'S' 
    AND opeExcluido = 'N' 
    AND vopAtivo = 'S' 
    AND vopExcluido = 'N' 

ORDER BY 
    RAND() 

LIMIT 
    0,4;