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

时间:2012-05-18 13:31:07

标签: mysql sql-update

我的情况如下:

我有一张表articles,其中包含以下详细信息:

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

和其他带有此数据的article_images表:

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

我需要像这样更新表格文章:

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

我知道这似乎不是很难,但在谷歌上找不到一个例子是不可能的。有人可以帮帮我吗?

3 个答案:

答案 0 :(得分:1)

如果您可以在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

然后这应该有效:

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

答案 1 :(得分:1)

使用单独的“article_images”表格的当前方法是最好的方法。这种表是关系数据库的基础!如果您必须在同一行中有前3个图像的文章,那么我建议您创建一个视图,并保留当前的表结构。视图可以定义为:

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

答案 2 :(得分:1)

此查询将生成所需的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);

有点复杂,但这个子查询可以在MySQL + PostgreSQL中使用。

要更新使用(此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;

如果您的数据库支持窗口函数+ 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;

现在,每篇文章只有一行,但您可以使用此子查询进行更新:

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;

UPDATE查询将在PostgreSQL中运行,但可能不会在ORACLE / SQL Server上运行。

您可以使用MySQLPostgreSQL变体。