mysql—如何编写结果集由两列唯一的sql语句?

siotufzp  于 2021-06-15  发布在  Mysql
关注(0)|答案(2)|浏览(283)

如何编写一个sql(mysql数据库)语句来返回一个与两列相关的唯一结果集?
为了使我的问题尽可能简单,假设我只有两张table images 以及 products . 我想查询一组特定产品的所有图像,这些图像都有这个字符串 Swatch 在野外, images . 此查询通过使用mysql数据库的以下sql成功:

SELECT 
    images.alt,
    images.product_id,
    images.src
FROM
    images
    INNER JOIN products
        ON products.product_id IN (
            "2112055640177",
            "2112056590449",
            "2112055378033",
            "2112062292081",
            "2112058490993",
            "2112062619761",
            "2112062488689",
            "2112066420849",
            "2112061833329",
            "2112052527217"
        )
WHERE 
    images.alt LIKE "%Swatch%";

但是,结果集充满了重复项:

Black Tuscan - Swatch   2112049971313   foobar.com
Black Tuscan - Swatch   2112049971313   foobar.com
Black Tuscan - Swatch   2112049971313   foobar.com
Generic Black - Swatch  2112049971313   baz.com
Generic Black - Swatch  2112049971313   baz.com
Florence - Swatch   2112049971313   foobaz.com
Florence - Swatch   2112049971313   foobaz.com
Gold - Swatch   2112050593905   bazfoo.com
Gold - Swatch   2112050593905   bazfoo.com
Sand - Swatch   2112050593905   bazfoo.com
Sand - Swatch   2112050593905   bazfoo.com

每个产品id图像集都有副本(例如: Black Tuscan - Swatch 2112049971313 foobar.com , Black Tuscan - Swatch 2112049971313 foobar.com )
我希望结果集不包含重复的产品样本。换言之,images.alt和images.product\u id的图像应该是唯一的。理想情况下,结果集应该是以下内容,而不是上面的返回值:

Black Tuscan - Swatch   2112049971313   foobar.com
Generic Black - Swatch  2112049971313   baz.com
Florence - Swatch   2112049971313   foobaz.com
Gold - Swatch   2112050593905   bazfoo.com
Sand - Swatch   2112050593905   bazfoo.com
Black Tuscan - Swatch   1234586923813   foobar.com
Sand - Swatch   1234586923813   bazfoo.com

请注意,对于每个产品标识,没有重复的alt text值。
我已经做了很多搜索,我发现这些所谓的职位(一,二,三)。他们建议使用 LEFT JOIN ,或 GROUP BY ,或 DISTINCT 但是我还没有找到正确的sql语句来获得我正在寻找的唯一性-unique by images.alt和images.product\u id。

jyztefdp

jyztefdp1#

您的联接被搞砸了,因为它无法将表关联在一起。我想你需要更像这样的东西:

SELECT images.alt, images.product_id, images.src
FROM images
INNER JOIN products
ON products.product_id = images.product_id
WHERE products.product_id IN ("2112055640177","2112056590449","2112055378033","2112062292081","2112058490993","2112062619761","2112062488689","2112066420849","2112061833329","2112052527217") and
images.alt LIKE "%Swatch%";

至于为什么会出现复制品,这被称为笛卡尔积。当连接条件被打破时,彼此不相关的行最终被连接起来。
如果你有2个产品和3个图像,你做到了:

products JOIN images ON 1=1

连接条件始终为真,每个图像将复制2次,每个产品显示3次

P1,i1
P1,i2
P1,i3
P2,i1
P2,i2
P2,i3

这可能有助于您理解数据库是如何联接数据的:它们将此表中的每一行与该表中的每一行合并,然后删除不符合联接条件中条件的合并行
在您最初的查询中,如果有38个带有“swatch”的图像和10个产品,您将得到30行,因为10个产品行中的每一行都与3个图像中的每一个相结合。如果您有100个产品和100个图像,设想db将所有组合合并,生成10000行,然后删除不符合in的行(不允许使用90/100产品,删除90%的行,删除9000行,留下1000行),然后删除不符合where的所有行(97/100图像没有样本,97%的行被删除,970行被删除,剩下30行)
因为您没有选择所有列(select*),所以您看不到使每一行唯一的变体。。把它放进去,你会看到的
不要使用distinct删除重复项,修复导致笛卡尔积的断开连接条件

tsm1rwdh

tsm1rwdh2#

你不需要一个 JOIN 所有的产品。那也许能解决你的问题。

SELECT i.alt, i.product_id, i.src
FROM images i
WHERE i.product_id IN ('2112055640177', '2112056590449', '2112055378033', '2112062292081', '2112058490993', '2112062619761', '2112062488689', '2112066420849', '2112061833329', '2112052527217')
WHERE i.alt LIKE '%Swatch%';

如果这不能解决你的问题,那就用 GROUP BY :

SELECT i.alt, i.product_id, MAX(i.src)
FROM images i
WHERE i.product_id IN ('2112055640177', '2112056590449', '2112055378033', '2112062292081', '2112058490993', '2112062619761', '2112062488689', '2112066420849', '2112061833329', '2112052527217')
WHERE i.alt LIKE '%Swatch%'
GROUP BY i.alt, i.product_id;

如果你真的想从 products ,你需要做 JOIN 正确地:

SELECT . . .
FROM images i JOIN
     products p
     USING (product_id)
WHERE p.product_id IN ('2112055640177', '2112056590449', '2112055378033', '2112062292081', '2112058490993', '2112062619761', '2112062488689', '2112066420849', '2112061833329', '2112052527217')
WHERE i.alt LIKE '%Swatch%';

相关问题