【问题标题】:shift column data if column1 is empty and make other column NULL如果 column1 为空,则移动列数据并使其他列为 NULL
【发布时间】:2014-10-01 09:17:42
【问题描述】:

我有一个多列的表。我想使用 PHP 和 MYSQL 编写 UPDATE 查询,如果只有 Col1 数据为 NULL,它会移动列数据。 例如:

原始表

+--------------+--------------+---------------+ --------------+
| Col1      | Col2      | Col3      | Col4      |
+---------------+--------------+---------------+--- ------------+
| NULL      | dat1       | dat2      | dat3      |
+---------------+--------------+---------------+--- ------------+
| NULL      | dat1       | NULL     | dat3      |
+--------------+--------------+-------------- -+--------------+
| dat0      | dat1       | NULL      | dat3      |
+--------------+--------------+-------------- -+--------------+
| NULL      | NULL      | dat2      | dat3      |
+---------------+--------------+---------------+--- ------------+

输出表将在下方

+--------------+--------------+---------------+ --------------+
| Col1      | Col2      | Col3      | Col4      |
+---------------+--------------+---------------+--- ------------+
| dat1      | dat2       | dat3      | NULL      |
+---------------+--------------+---------------+--- ------------+
| dat1      | dat3       | NULL     | NULL      |
+--------------+-------------+-------------- -+--------------+
| dat0      | dat1       | NULL      | dat3      |
+--------------+--------------+-------------- -+--------------+
| dat2      | dat3      | NULL      | NULL      |

【问题讨论】:

  • 为什么dat3 被移动到第二行,而机器人没有被移动到第三行?
  • @sectus:因为Col1 不是NULL
  • 看起来你有一个非规范化的数据结构,并且想要做一些如果数据存储在行而不是列中会更容易的事情。
  • :D 下次使用代码按钮而不是千位  ;)

标签: mysql sql


【解决方案1】:

col1NULL 时,您似乎想将所有值移至左侧。您可以使用蛮力逻辑来做到这一点,这对于四列来说还不错:

UPDATE table
  SET Col1 = coalesce(Col2, col3, col4),
      col2 = (case when col2 is not null then coalesce(col3, col4)
                   when col3 is not null then col4
              end),
      col3 = (case when col2 is not null and col3 is not null then col4 end),
      col4 = NULL
  WHERE Col1 IS NULL;

【讨论】:

  • 是的,实际上我在表中有 9 列,我只是为了得到这个想法而放了 4。但似乎更新查询太长了。请用不止一个查询给我这个或其他方式的想法。
  • @user3591167 。 . .您的问题是关于 4 列,而不是 9 列。
【解决方案2】:

一个适用于任意列数的 php 脚本,但它每行运行 1 次更新,所以如果你有很多行,它会很慢。

$query = "SELECT * FROM myTable WHERE Col1 IS NULL";
$rs = mysqli_query($query);

while($r = mysqli_fetch_assoc($rs)) {

    $non_null = array_filter($r);
    $update = array();

    foreach($r as $key => $value) {        
        $update[$key] = current($non_null);
        next($non_null);
    }

    $updateQuery = "UPDATE myTable SET ";
    $comma = '';

    foreach($update as $key => $value) {
        if(false === $value) {
            $updateQuery .= " $comma $key = NULL ";
        }
        else {
            $updateQuery .= " $comma $key = '$value' ";
        }
        $comma = ',';
    }

    $updateQuery .= " WHERE ";
    $and = '';

    foreach($r as $key => $value) {
        if(is_null($value)) {
            $updateQuery .= " $and $key IS NULL ";
        }
        else {
            $updateQuery .= " $and $key = '$value' ";
        }
        $and = 'AND';
    }

    mysqli_query($updateQuery);
}

【讨论】:

  • @user3591167 你能再试一次更新吗?如果它仍然不起作用打印 $updateQuery
  • 我用while($r = mysqli_fetch_assoc($query)) { 代替while($r = mysqli_fetch_assoc($rs)) { 效果很好。谢谢
【解决方案3】:
SELECT
    Phone1_Business = MIN(CASE WHEN y.rn = 1 THEN y.val END),
    Phone2_Business = MIN(CASE WHEN y.rn = 2 THEN y.val END),
    Phone3_Business = MIN(CASE WHEN y.rn = 3 THEN y.val END),
    Phone4_Business = MIN(CASE WHEN y.rn = 4 THEN y.val END),
    Phone5_Business = MIN(CASE WHEN y.rn = 5 THEN y.val END),
    Phone6_Business = MIN(CASE WHEN y.rn = 6 THEN y.val END),
    Phone7_Business = MIN(CASE WHEN y.rn = 7 THEN y.val END),
    Phone8_Business = MIN(CASE WHEN y.rn = 8 THEN y.val END),
    Phone9_Cell = MIN(CASE WHEN y.rn = 9 THEN y.val END),
    Phone10_Cell = MIN(CASE WHEN y.rn = 10 THEN y.val END),
    Phone11_Cell = MIN(CASE WHEN y.rn = 11 THEN y.val END),
    Phone12_Cell = MIN(CASE WHEN y.rn = 12 THEN y.val END),
    Phone13_Cell = MIN(CASE WHEN y.rn = 13 THEN y.val END),
    Phone14_Cell = MIN(CASE WHEN y.rn = 14 THEN y.val END),
    Phone15_Other = MIN(CASE WHEN y.rn = 15 THEN y.val END)
FROM #temp1 
OUTER APPLY
( SELECT
x.val,
rn = ROW_NUMBER() OVER (ORDER BY rn)
FROM
( VALUES 
(Phone1_Business,1), (Phone2_Business,2), (Phone3_Business,3), (Phone4_Business,4), (Phone5_Business,5), (Phone6_Business,6)
, (Phone7_Business,7), (Phone8_Business,8), (Phone9_Cell,9), (Phone10_Cell,10), (Phone11_Cell,11), (Phone12_Cell,12)
, (Phone13_Cell,13), (Phone14_Cell,14), (Phone15_Other,15)
) x (val, rn) 
WHERE x.val IS NOT NULL
) y 
GROUP BY 
#temp1.RecordID ;

【讨论】:

  • 虽然此代码可能会回答问题,但提供有关它如何和/或为什么解决问题的额外上下文将提高​​答案的长期价值。
猜你喜欢
  • 2013-09-01
  • 1970-01-01
  • 2022-07-11
  • 1970-01-01
  • 1970-01-01
  • 2021-06-03
  • 2015-05-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多