我怎么能交换两个值

时间:2017-08-22 19:15:55

标签: sql oracle sql-update

我有以下数据。

TRACK_ID      CT_ID           IMAGE_SORT_NO       IMAGE_LEVEL
132071        63461               1                image_1
132081        63461               2                image_2
132091        63461               3                image_3

Image_sort_no是主键。每个image_sort_no都有一张图片。我必须将1到3和3的值交换为1.我的预期输出看起来像

TRACK_ID      CT_ID           IMAGE_SORT_NO       IMAGE_LEVEL
132071        63461               1                image_3
132081        63461               2                image_2
132091        63461               3                image_1

如果我运行以下更新语句,那么我将丢失1的image_level。

Update cd_offender
   set image_level = image_3
 Where IMAGE_SORT_NO = 1;

如何在不丢失任何内容的情况下交换值?

2 个答案:

答案 0 :(得分:1)

尝试:

With xxx As (
  SELECT *
  FROM (
    SELECT IMAGE_SORT_NO As min_sort_no, 
           IMAGE_LEVEL As min_IMAGE_LEVEL
    FROM cd_offender
    ORDER BY IMAGE_SORT_NO LIMIT 1
  ) x
  CROSS JOIN (
    SELECT IMAGE_SORT_NO As max_sort_no, 
           IMAGE_LEVEL As max_IMAGE_LEVEL
    FROM cd_offender
    ORDER BY IMAGE_SORT_NO DESC LIMIT 1
  ) y
)
UPDATE cd_offender t
SET IMAGE_LEVEL = CASE
    WHEN IMAGE_SORT_NO = xxx.min_sort_no THEN xxx.max_image_level
    WHEN IMAGE_SORT_NO = xxx.max_sort_no THEN xxx.min_image_level
    ELSE IMAGE_LEVEL -- just to be on the safe side
END
FROM xxx
WHERE IMAGE_SORT_NO IN (xxx.min_sort_no, xxx.max_sort_no )
;

演示:http://sqlfiddle.com/#!17/8e19d/6

答案 1 :(得分:0)

这将仅在第一个和最后一个值之间交换image_level的值

SELECT t1.track_id,
       t1.ct_id,
       t1.image_sort_no,
       CASE WHEN t1.image_sort_no = t2.firstsort THEN t2.firstvalue
            WHEN t1.image_sort_no = t2.lastsort THEN t2.lastvalue
            ELSE t1.image_level
        END image_level
  FROM cd_offender t1
  LEFT OUTER JOIN (SELECT ct_id,       
                          MAX(image_sort_no) KEEP (DENSE_RANK FIRST ORDER BY image_sort_no) firstsort,
                          MAX(image_level) KEEP (DENSE_RANK LAST ORDER BY image_sort_no) firstvalue,
                          MAX(image_sort_no) KEEP (DENSE_RANK LAST ORDER BY image_sort_no) lastsort,
                          MAX(image_level) KEEP (DENSE_RANK FIRST ORDER BY image_sort_no) lastvalue
                     FROM cd_offender
                    GROUP BY ct_id) t2
    ON t1.ct_id = t2.ct_id
 ORDER BY t1.ct_id,
          t1.track_id,       
          t1.image_sort_no;

更新

MERGE INTO cd_offender 
USING 
(
  SELECT t1.track_id,
       t1.ct_id,
       t1.image_sort_no,
       CASE WHEN t1.image_sort_no = t2.firstsort THEN t2.firstvalue
            WHEN t1.image_sort_no = t2.lastsort THEN t2.lastvalue
            ELSE t1.image_level
        END image_level
  FROM cd_offender t1
  LEFT OUTER JOIN (SELECT ct_id,       
                          MAX(image_sort_no) KEEP (DENSE_RANK FIRST ORDER BY image_sort_no) firstsort,
                          MAX(image_level) KEEP (DENSE_RANK LAST ORDER BY image_sort_no) firstvalue,
                          MAX(image_sort_no) KEEP (DENSE_RANK LAST ORDER BY image_sort_no) lastsort,
                          MAX(image_level) KEEP (DENSE_RANK FIRST ORDER BY image_sort_no) lastvalue
                     FROM cd_offender
                    GROUP BY ct_id) t2
    ON t1.ct_id = t2.ct_id
 ORDER BY t1.ct_id,
          t1.track_id,       
          t1.image_sort_no
) ta  ON (ta.track_id = t_image.track_id
     AND ta.ct_id = t_image.ct_id
     AND ta.image_sort_no = t_image.image_sort_no)
  WHEN MATCHED THEN UPDATE 
   SET t_image.image_level = ta.image_level;