LEFT JOIN select 左联接的最新行

LEFT JOIN select latest row from the left join

我有一个公司数据库,其中包含所有详细信息。它还有一个单独的 table 存储信用评级。

DROP TABLE IF EXISTS `company`;
CREATE TABLE IF NOT EXISTS `company` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) CHARACTER SET latin1 NOT NULL,
  `email` varchar(255) CHARACTER SET latin1 NOT NULL,
  `address` varchar(255) NOT NULL,
  `address2` text NOT NULL,
  `address3` text NOT NULL,
  `phone` text NOT NULL,
  `contacts` text NOT NULL,
  `islive` tinyint(1) NOT NULL DEFAULT '1',
  `qt` tinyint(1) NOT NULL DEFAULT '30',
  `pt` tinyint(1) NOT NULL DEFAULT '30',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

DROP TABLE IF EXISTS `creditrating`;
CREATE TABLE IF NOT EXISTS `creditrating` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `cid` int(11) NOT NULL,
  `rating` int(11) NOT NULL,
  `arating` varchar(10) NOT NULL,
  `type` tinyint(1) NOT NULL DEFAULT '1',
  `thedate` datetime NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

INSERT INTO `company` (`id`, `name`, `email`, `address`, `address2`, `address3`, `phone`, `contacts`, `islive`, `qt`, `pt`) VALUES
(190, 'Test Company', 'test@test.com', 'Testing Client 1\r\nsdfsdfsdf\r\nsdfsdfsdf', 'Testing Client 1\r\nsdfsdfsdf\r\nsdfsdfsdf', 'Testing Client 1\r\nsdfsdfsdf\r\nsdfsdfsdf', '65165156', 'test name', 1, 30, 30),
(191, 'Test Company 2', 'test2@test2.com', 'Testing Client 2\r\nsdfsdfsdf\r\nsdfsdfsdf', 'Testing Client 2\r\nsdfsdfsdf\r\nsdfsdfsdf', 'Testing Client 2\r\nsdfsdfsdf\r\nsdfsdfsdf', '65165156', 'test name 2', 1, 30, 30);

INSERT INTO `creditrating` (`id`, `cid`, `rating`, `arating`, `type`, `thedate`) VALUES
(3, 190, 684, 'da774', 1, '2021-03-30 15:08:52'),
(6, 190, 222, 'DD222', 1, '2021-03-30 17:46:22');

我试图只检索公司详细信息和信用评级的最新行 table。

我最接近让它工作的 SQL 是 (Mysql 5.6):

SELECT c.id
     , AES_DECRYPT(c.name, 'co1') as name
     , AES_DECRYPT(c.phone, 'co3') as phone
     , c.islive
     , r.rating 
  FROM company c 
  LEFT 
  JOIN creditrating r 
    ON (SELECT r.thedate FROM creditrating WHERE c.id=r.cid ORDER BY r.thedate DESC LIMIT 1)

DB FIDDLE HERE

目前它正在带回同一家公司的 2 行,而不仅仅是 1 行。

在此先感谢大家对我的指导。

您可以为此使用 window 函数:

SELECT c.id, AES_DECRYPT(c.name, 'co1') as name, AES_DECRYPT(c.phone, 'co3') as phone, c.islive, r.rating
FROM company c LEFT JOIN
     (SELECT r.*,
              ROW_NUMBER() OVER (PARTITION BY r.cid ORDER BY r.thedate DESC) as seqnum
      FROM creditrating r
     ) r
     ON c.id = r.cid AND r.seqnum = 1;

以前的版本没有 window 函数,但您可以切换到用户定义的变量

DROP TABLE IF EXISTS `company`;
CREATE TABLE IF NOT EXISTS `company` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) CHARACTER SET latin1 NOT NULL,
  `email` varchar(255) CHARACTER SET latin1 NOT NULL,
  `address` varchar(255) NOT NULL,
  `address2` text NOT NULL,
  `address3` text NOT NULL,
  `phone` text NOT NULL,
  `contacts` text NOT NULL,
  `islive` tinyint(1) NOT NULL DEFAULT '1',
  `qt` tinyint(1) NOT NULL DEFAULT '30',
  `pt` tinyint(1) NOT NULL DEFAULT '30',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

DROP TABLE IF EXISTS `creditrating`;
CREATE TABLE IF NOT EXISTS `creditrating` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `cid` int(11) NOT NULL,
  `rating` int(11) NOT NULL,
  `arating` varchar(10) NOT NULL,
  `type` tinyint(1) NOT NULL DEFAULT '1',
  `thedate` datetime NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

INSERT INTO `company` (`id`, `name`, `email`, `address`, `address2`, `address3`, `phone`, `contacts`, `islive`, `qt`, `pt`) VALUES
(190, 'Test Company', 'test@test.com', 'Testing Client 1\r\nsdfsdfsdf\r\nsdfsdfsdf', 'Testing Client 1\r\nsdfsdfsdf\r\nsdfsdfsdf', 'Testing Client 1\r\nsdfsdfsdf\r\nsdfsdfsdf', '65165156', 'test name', 1, 30, 30),
(191, 'Test Company 2', 'test2@test2.com', 'Testing Client 2\r\nsdfsdfsdf\r\nsdfsdfsdf', 'Testing Client 2\r\nsdfsdfsdf\r\nsdfsdfsdf', 'Testing Client 2\r\nsdfsdfsdf\r\nsdfsdfsdf', '65165156', 'test name 2', 1, 30, 30);

INSERT INTO `creditrating` (`id`, `cid`, `rating`, `arating`, `type`, `thedate`) VALUES
(3, 190, 684, 'da774', 1, '2021-03-30 15:08:52'),
(6, 190, 222, 'DD222', 1, '2021-03-30 17:46:22');
SELECT 
    id, name, phone, islive, rating, `thedate`
FROM
    (SELECT 
        name,
            phone,
            islive,
            rating,
            `thedate`,
            IF(id = @id, @rnk:=@rnk + 1, @rnk:=1) AS rnk,
            @id:=id AS id
    FROM
        (SELECT 
        c.id,
            AES_DECRYPT(c.name, 'co1') AS name,
            AES_DECRYPT(c.phone, 'co3') AS phone,
            c.islive,
            r.rating,
            `thedate`
    FROM
        company c
    LEFT JOIN creditrating r ON c.id = r.cid) t1, (SELECT @id:=- 1, @rnk:=0) t2
    ORDER BY id , `thedate` DESC) t3
WHERE
    rnk = 1;
 id | name | phone | islive | rating | thedate            
--: | :--- | :---- | -----: | -----: | :------------------
190 | null | null  |      1 |    222 | 2021-03-30 17:46:22
191 | null | null  |      1 |   null | null               

db<>fiddle here