简体   繁体   English

从另一个表的行更新一个表中的列

[英]Update columns in one table from rows of another table

My case is as follow: 我的情况如下:

I have a table articles with these details: 我有一个表格articles ,其中包含以下详细信息:

    article | image1 | image2 | image3 
    ---------------------------------    
      1     | im-x
      2     | im-y
      3     | im-z 

and other article_images table with this data: 以及其他具有此数据的article_images表:

    article | image    
    ---------------    
        1   | im-a
        1   | im-b
        2   | im-c
        2   | im-d
        3   | im-e 

I need to update the table articles like this: 我需要像这样更新表文章:

    article | image1 | image2 | image3    
    ---------------------------------    
       1    | im-x   | im-a   | im-b
       2    | im-y   | im-c   | im-d    
       3    | im-z   | im-e   | 

I know it seems not very difficult, but impossible to find an example on google. 我知道这似乎不是很困难,但不可能在Google上找到示例。 Can anyone help me, please? 有人可以帮我吗?

If you can add an additional colum to the article_images table and identify which colum the image needs to go in: 如果您可以在article_images表中添加一个额外的列,并确定图像需要进入哪个列:

    article | image | col
    ------------------------    
        1   | im-a  | image2
        1   | im-b  | image3
        2   | im-c  | image3
        2   | im-d  | image2
        3   | im-e  | image3

Then this should work: 然后这应该工作:

update articles 

  set image1 = CASE WHEN col = 'image1' THEN image else image1 END,
      image2 = CASE WHEN col = 'image2' THEN image else image2 END,
      image3 = CASE WHEN col = 'image3' THEN image else image3 END

  from articles inner join article_images
  on articles.article = article_images.article

Your current approach with a separate "article_images" table is the best approach. 当前的方法是使用单独的“ article_images”表,这是最好的方法。 This kind of table is the bread and butter of a relational database! 这种表是关系数据库的基础! If it is essential that you have an article with the first 3 images in the same row then I would suggest creating a view, and keeping your current table structure. 如果必须在同一行中包含前三幅图像,那么我建议您创建一个视图并保留当前的表格结构。 The view could be defined as: 该视图可以定义为:

SELECT  ar.Article,
        MIN(img1.Image) AS Image1,
        MIN(img2.Image) AS Image2,
        MIN(img3.Image) AS Image3
FROM    Articles ar
        LEFT JOIN Article_images img1
            ON img1.Article = ar.Article
        LEFT JOIN Article_images img2
            ON img2.Article = ar.Article
            AND img2.Image > img1.Image
        LEFT JOIN Article_images img3
            ON img3.Article = ar.Article
            AND img3.Image > img2.Image
GROUP BY ar.Article

Live Test at SQL Fiddle SQL Fiddle的实时测试

This query will produce the desired Pivot: 此查询将产生所需的数据透视:

SELECT a.article, coalesce(i1.image,'') AS img1, coalesce(i2.image, '') AS img2
  FROM (SELECT article FROM article_images GROUP BY article) a
  LEFT JOIN article_images i1 ON a.article = i1.article AND i1.image =
       (SELECT image FROM article_images WHERE article = a.article
         ORDER BY image LIMIT 1)
  LEFT JOIN article_images i2 ON a.article = i2.article AND i2.image =
       (SELECT image FROM article_images WHERE article = a.article
         ORDER BY image LIMIT 1 OFFSET 1);

A bit complicated, but this subquery will work in MySQL + PostgreSQL. 有点复杂,但是此子查询将在MySQL + PostgreSQL中运行。

To update use (this UPDATE is MySQL specific): 要更新使用(此UPDATE是MySQL特定的):

UPDATE articles a, (SELECT a.article, coalesce(i1.image, '') AS img1,
                    coalesce(i2.image, '') AS img2
  FROM (SELECT article FROM article_images GROUP BY article) a
  LEFT JOIN article_images i1 ON a.article = i1.article AND i1.image =
       (SELECT image FROM article_images WHERE article = a.article
         ORDER BY image LIMIT 1)
  LEFT JOIN article_images i2 ON a.article = i2.article AND i2.image =
       (SELECT image FROM article_images WHERE article = a.article
         ORDER BY image LIMIT 1 OFFSET 1)) AS s
SET a.image2 = s.img1, a.image3 = s.img2
WHERE a.article = s.article;

If your database support window functions + CTE, like SQL Server, PostgreSQL or ORACLE, the following query can be used instead to generate Pivot: 如果您的数据库支持窗口功能+ CTE(例如SQL Server,PostgreSQL或ORACLE),则可以使用以下查询来生成Pivot:

WITH rowed AS (
  SELECT article, image,
         row_number() OVER (PARTITION BY article ORDER BY image) AS row
    FROM article_images)
SELECT a.article, coalesce(i1.image, '') AS img1, coalesce(i2.image, '') AS img2
  FROM (SELECT article FROM article_images GROUP BY article) AS a
  LEFT JOIN rowed i1 ON i1.article = a.article AND i1.row = 1
  LEFT JOIN rowed i2 ON i2.article = a.article AND i2.row = 2;

Now you have a single row per article in a shorter way and you can use this subquery to update: 现在,您可以以较短的方式在每篇文章中拥有一行,并且可以使用此子查询来更新:

UPDATE articles a
SET image2 = s.img1,
    image3 = s.img2
FROM (WITH rowed AS (
  SELECT article, image,
         row_number() OVER (PARTITION BY article ORDER BY image) AS row
    FROM article_images)
  SELECT a.article, coalesce(i1.image, '') AS img1, coalesce(i2.image, '') AS img2
     FROM (SELECT article FROM article_images GROUP BY article) AS a
      LEFT JOIN rowed i1 ON i1.article = a.article AND i1.ROW = 1
      LEFT JOIN rowed i2 ON i2.article = a.article AND i2.ROW = 2) AS s
WHERE a.article = s.article;

This UPDATE query will work in PostgreSQL, but likely it wont on ORACLE / SQL Server. UPDATE查询可在PostgreSQL中使用,但可能不会在ORACLE / SQL Server上使用。

You can play around with MySQL and PostgreSQL variants. 您可以使用MySQLPostgreSQL变体。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM