显示左外连接的最后一行

Show last line with left outer join

我的语法有问题,我需要使用内部连接显示最后一条记录,我使用这个例子(SQL join: selecting the last records in a one-to-many relationship)作为基础但我还是不行,总是出现在第一条,可以有人帮我告诉我我错了吗? 我的代码:

select dc.nome,ep.documento,cc.dataVenc,cv.* from contratoscliente cc 
inner join em_processo ep on ep.id = cc.em_processo_id 
inner join dadoscliente dc on dc.em_processo_id = ep.id  
join contratoscliente_has_contratosvenc cccv on cccv.contratoscliente_id = cc.id 
join contratosvenc cv on (cccv.contratosvenc_id = cv.id) 
left outer join contratosvenc cv2 on (cccv.contratosvenc_id = cv2.id AND 
    (cv.vencimento < cv2.vencimento OR (cv.vencimento = cv2.vencimento AND cv.id < cv2.id))) WHERE (cv2.id IS NULL or cv.id=cv2.id) GROUP BY ep.id;

我的表:

合同客户: contratosclientes

contratosclientes_has_contratosvenc: contratosclientes_has_contratosvenc

合同: contratosvenc

查询结果: Result Query Wrong

字段 'vencimento' 和 'valororiginal' 出现在第一个结果中,我希望它出现在最后一个结果中...... 我的 SQL 个表:

    DROP TABLE IF EXISTS `contratoscliente`;
CREATE TABLE `contratoscliente`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `status` varchar(255) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL,
  `perfilCobranca` varchar(255) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL,
  `statusPerfil` varchar(255) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL,
  `tipoConta` varchar(255) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL,
  `formaEnvio` varchar(255) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL,
  `dataVenc` varchar(255) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL,
  `enderecFatura` varchar(255) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL,
  `formaPagto` varchar(255) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL,
  `controleConta` varchar(255) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL,
  `contaDetalhadaInternet` varchar(255) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL,
  `icms` varchar(255) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL,
  `dataStatusCobranca` varchar(255) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL,
  `statusCobranca` varchar(255) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL,
  `dataFechamento` varchar(255) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL,
  `compartilhavel` varchar(255) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL,
  `statusPerfilFaturamento` varchar(255) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL,
  `programacaofaturamento` varchar(255) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL,
  `em_processo_id` int(11) NOT NULL,
  `dado_processado_em` timestamp(0) NULL DEFAULT CURRENT_TIMESTAMP(0),
  PRIMARY KEY (`id`) USING BTREE,
  INDEX `fk_dadoscliente_em_processo1_idx`(`em_processo_id`) USING BTREE,
  CONSTRAINT `contratoscliente_ibfk_1` FOREIGN KEY (`em_processo_id`) REFERENCES `em_processo` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE = InnoDB AUTO_INCREMENT = 1946 CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Dynamic;

INSERT INTO `contratoscliente` VALUES (1945, '', '05050505', 'Ativo', 'Resumida', 'Papel', '15', 'restrict', 'Fatura', 'Marcada', 'Marcada', 'Padrão', ' ', 'Aviso de rescisão contratual', '26', '', 'Ativo', ' ', 86, '2019-09-04 17:03:33');

DROP TABLE IF EXISTS `contratoscliente_has_contratosvenc`;
CREATE TABLE `contratoscliente_has_contratosvenc`  (
  `contratoscliente_id` int(11) NOT NULL,
  `contratosvenc_id` int(11) NOT NULL,
  PRIMARY KEY (`contratoscliente_id`, `contratosvenc_id`) USING BTREE,
  INDEX `contratoscliente_id`(`contratoscliente_id`) USING BTREE,
  INDEX `contratosvenc_id`(`contratosvenc_id`) USING BTREE,
  CONSTRAINT `contratoscliente` FOREIGN KEY (`contratoscliente_id`) REFERENCES `contratoscliente` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
  CONSTRAINT `contratovenc` FOREIGN KEY (`contratosvenc_id`) REFERENCES `contratosvenc` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE = InnoDB CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Dynamic;


INSERT INTO `contratoscliente_has_contratosvenc` VALUES (1945, 23358);
INSERT INTO `contratoscliente_has_contratosvenc` VALUES (1945, 23359);
INSERT INTO `contratoscliente_has_contratosvenc` VALUES (1945, 23360);
INSERT INTO `contratoscliente_has_contratosvenc` VALUES (1945, 23361);

DROP TABLE IF EXISTS `contratosvenc`;
CREATE TABLE `contratosvenc`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `vencimento` date NULL DEFAULT NULL,
  `valorOriginal` varchar(255) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL,
  `valorAjuste` varchar(255) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL,
  `valorFinal` varchar(255) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL,
  `historicoFatura` varchar(255) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL,
  `dataPagamento` varchar(255) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL,
  `detalhesPagamento` varchar(255) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 23362 CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Dynamic;
INSERT INTO `contratosvenc` VALUES (23358, '2019-02-15', 'R$ 71.28', 'R$ 0.00', 'R$ 71.28', 'Paga', '19/02/2019', 'Caixa econômica Federal - LBX Pagamento Loterica');
INSERT INTO `contratosvenc` VALUES (23359, '2019-03-15', 'R$ 86.49', 'R$ 0.00', 'R$ 86.49', 'Não Paga', ' ', ' ');
INSERT INTO `contratosvenc` VALUES (23360, '2019-04-15', 'R$ 85.00', 'R$ 0.00', 'R$ 85.00', 'Não Paga', ' ', ' ');
INSERT INTO `contratosvenc` VALUES (23361, '2019-05-15', 'R$ 85.00', 'R$ 0.00', 'R$ 85.00', 'Não Paga', ' ', ' ');


DROP TABLE IF EXISTS `dadoscliente`;
CREATE TABLE `dadoscliente`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `nome` varchar(255) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL,
  `endereco` varchar(255) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL,
  `contato_principal` varchar(255) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL,
  `telefone_principal` varchar(255) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL,
  `telefone_residencial` varchar(255) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL,
  `telefone_comercial` varchar(255) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL,
  `email` varchar(255) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL,
  `em_processo_id` int(11) NOT NULL,
  `dado_processado_em` timestamp(0) NULL DEFAULT CURRENT_TIMESTAMP(0),
  PRIMARY KEY (`id`) USING BTREE,
  INDEX `fk_dadoscliente_em_processo1_idx`(`em_processo_id`) USING BTREE,
  CONSTRAINT `fk_dadoscliente_em_processo1` FOREIGN KEY (`em_processo_id`) REFERENCES `em_processo` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE = InnoDB AUTO_INCREMENT = 1025 CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Dynamic;


INSERT INTO `dadoscliente` VALUES (1024, 'EFIGENIA CUSTODIA DE OLIVEIRA DE name teste', 'brazil', 'contatc', '(12) 12121212', '(12) 13131313', '', 'email@teste.com', 86, '2019-09-04 17:03:33');

DROP TABLE IF EXISTS `em_processo`;
CREATE TABLE `em_processo`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `documento` varchar(255) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL,
  `processado` int(11) NULL DEFAULT 0,
  `id_user_crm` int(11) NOT NULL,
  `servico` int(11) NOT NULL DEFAULT 1,
  `atuando` datetime(0) NULL DEFAULT NULL,
  `arquivo` int(11) NOT NULL DEFAULT 1,
  PRIMARY KEY (`id`) USING BTREE,
  INDEX `id`(`id`, `documento`, `processado`, `id_user_crm`, `atuando`, `arquivo`) USING BTREE,
  INDEX `arquivo`(`arquivo`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 90 CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Dynamic;

INSERT INTO `em_processo` VALUES (86, '0909090909', 1, 2, 6, '2019-09-04 17:03:08', 62);
INSERT INTO `em_processo` VALUES (87, '08080808', 0, 2, 6, '2019-09-04 17:03:08', 62);
INSERT INTO `em_processo` VALUES (89, '07070707', 0, 2, 6, '2019-09-04 17:03:08', 62);

您的情况与参考问题中的 "simple" 不同。由于您有一个 多对多 关系,您需要 "LEFT JOIN the INNER JOIN" 两个表(contratoscliente_has_contratosvenccontratosvenc)。它应该类似于以下内容:

select dc.nome,ep.documento,cc.dataVenc,cv.*
from contratoscliente cc 
inner join em_processo ep on ep.id = cc.em_processo_id 
inner join dadoscliente dc on dc.em_processo_id = ep.id  
join contratoscliente_has_contratosvenc cccv on cccv.contratoscliente_id = cc.id 
join contratosvenc cv on (cccv.contratosvenc_id = cv.id) 

-- need to compare all rows from contratosvenc table
-- with the same contratoscliente_id in contratoscliente_has_contratosvenc table
left join (contratoscliente_has_contratosvenc cccv2
     join  contratosvenc cv2 on cccv2.contratosvenc_id = cv2.id 
) on cccv2.contratoscliente_id = cc.id AND
    (cv.vencimento < cv2.vencimento OR (cv.vencimento = cv2.vencimento AND cv.id < cv2.id))
WHERE cv2.id IS NULL

GROUP BY ep.id;

db-fiddle demo

但是 - 恕我直言,这是不可读的。我宁愿尝试在 ON 子句中使用 LIMIT 1 子查询的另一种方法:

select dc.nome,ep.documento,cc.dataVenc,cv.*
from contratoscliente cc 
inner join em_processo ep on ep.id = cc.em_processo_id 
inner join dadoscliente dc on dc.em_processo_id = ep.id  
join contratoscliente_has_contratosvenc cccv
  on  cccv.contratoscliente_id = cc.id 
  and cccv.contratosvenc_id = (
    select cv2.id
    from contratoscliente_has_contratosvenc cccv2
    join contratosvenc cv2 on cccv2.contratosvenc_id = cv2.id 
    where cccv2.contratoscliente_id = cc.id
    -- get the "latest" row only
    order by cv2.vencimento desc, cv2.id desc
    limit 1
  )
join contratosvenc cv on  cccv.contratosvenc_id = cv.id

第三种方法是使用 NOT EXISTS 子查询。它等同于 LEFT-JOIN-WHERE-NULL 方法,但恕我直言更具表现力。

select dc.nome,ep.documento,cc.dataVenc,cv.*
from contratoscliente cc 
inner join em_processo ep on ep.id = cc.em_processo_id 
inner join dadoscliente dc on dc.em_processo_id = ep.id  
join contratoscliente_has_contratosvenc cccv on cccv.contratoscliente_id = cc.id 
join contratosvenc cv on (cccv.contratosvenc_id = cv.id) 
-- get the row if there doesn't exist a "more current" row
where not exists (
  select *
  from contratoscliente_has_contratosvenc cccv2
  join contratosvenc cv2 on cccv2.contratosvenc_id = cv2.id 
  where cccv2.contratoscliente_id = cc.id
    and (cv.vencimento < cv2.vencimento OR (cv.vencimento = cv2.vencimento AND cv.id < cv2.id))
)

demo