【问题标题】:Retrieve only one record from LEFT JOIN从 LEFT JOIN 中仅检索一条记录
【发布时间】:2018-11-10 02:48:05
【问题描述】:

我有两张表,一张存储广告 (ads) 和其他存储图像 (images)。 images 通常在ads 中的每条记录中包含多个图像。

ads

+------------+------------+
|ad_id       |title       |
+------------+------------+
|1           |sample1     |
+------------+------------+
|2           |sample2     |
+------------+------------+

images

+------------+------------+
|image_id    |image       |
+------------+------------+
|1           |1.jpg       |
+------------+------------+
|1           |2.jpg       |
+------------+------------+
|2           |3.jpg       |
+------------+------------+

我想要做的是制作一个广告列表,在ads 中的每条记录中包含一张图片,并且当前使用以下 sql 查询。

SELECT a.`title`, i.`image`
FROM ads a
LEFT JOIN `images` i ON i.`id` = a.`id` 

但这会返回三个记录而不是两个广告,其中包含来自 ads 的重复记录,因为 images 包含两条图像记录。

如何在广告中限制每条记录只能使用一张图片。

任何帮助将不胜感激。 TIA

PS: 当前输出是这样的

sample1, 1.jpg
sample1, 2.jpg
sample2, 3.jpg

但我期待

sample1, 1.jpg
sample2, 3.jpg

sample1, 2.jpg
sample2, 3.jpg

【问题讨论】:

  • 你的 dbms 是什么?和你的预期结果?
  • 因为images表中有两行image_id= 1
  • 嗨。这是一个常见问题解答。请始终在谷歌上搜索您的问题/问题/目标的许多清晰、简洁和特定的版本/措辞,带和不带您的特定字符串/名称,并阅读许多答案。将您发现的相关关键字添加到搜索中。如果您没有找到答案,请发布,使用 1 个变体搜索作为标签的标题和关键字。请参阅向下投票箭头鼠标悬停文本。如果您确实有要发布的非重复代码问题,请阅读并在minimal reproducible example 上采取行动。

标签: sql join group-by aggregate-functions


【解决方案1】:

LEFT JOIN 表示将在左侧由ON 条件匹配的表上,但它将全部匹配id = 1id = 2

您可以尝试使用聚合函数MINMAX oni.image` 列来满足您的期望。

如果你想得到1.jpg,你可以使用MIN,否则使用MAX

CREATE TABLE ads(
  ad_id INT,
  title VARCHAR(50)
);


INSERT INTO ads VALUES (1,'sample1');
INSERT INTO ads VALUES (2,'sample2');

CREATE TABLE images(
  image_id INT,
  image VARCHAR(50)
);


INSERT INTO images VALUES(1,'1.jpg');
INSERT INTO images VALUES(1,'2.jpg');
INSERT INTO images VALUES(2,'3.jpg');

查询 #1

SELECT a.`title`,MIN(i.`image`)
FROM ads a
LEFT JOIN `images` i ON i.`image_id` = a.`ad_id` 
GROUP BY  a.`title`;

| title   | MIN(i.`image`) |
| ------- | -------------- |
| sample1 | 1.jpg          |
| sample2 | 3.jpg          |

View on DB Fiddle

【讨论】:

    【解决方案2】:

    最简单的方法可能是关联子查询:

    SELECT a.title,
           (SELECT i.image
            FROM image` i 
            WHERE i.id = a.id 
            LIMIT 1
           ) as image
    FROM ads a;
    

    这会返回一个任意图像。您可以在子查询中添加ORDER BY 以获取特定图像,例如:

    • ORDER BY rand() 获取随机图片
    • ORDER BY i.id 获取最小的id
    • ORDER BY i.createDate DESC 获取最新的
    • 等等

    【讨论】:

      【解决方案3】:
      SELECT OG.tittle as Title, 
             OG.image as Image
      FROM 
      (
      SELECT a.title as tittle, 
             i.image as image,
              row_number() over (Partition BY i.image_id ORDER BY i.image_id ASC  ) as rn
      FROM ads a
      LEFT JOIN images i ON i.id = a.id
      ) OG
      WHERE rn =1
      

      此查询将根据基于行号的过滤,每条记录仅显示一张图像。

      有关加入的更多信息,请单击此处https://medium.com/@cdaniel7/run-down-of-sql-joins-434d9d03f2d

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-02-11
        • 1970-01-01
        • 2018-04-01
        • 2015-07-24
        • 2023-02-10
        • 1970-01-01
        • 2014-12-12
        • 1970-01-01
        相关资源
        最近更新 更多