我有一张这样的桌子:
|Name1 |Name2 | Name3 | Name4|
|------+------+-------+------|
|Zoe |NULL |NULL |NULL |
|Julia |NULL |NULL |NULL |
|NULL |Ashley|NULL |NULL |
|NULL |Belvet|NULL |NULL |
|NULL |Maria |NULL |NULL |
|NULL |NULL |Mark |NULL |
|NULL |NULL |Jane |NULL |
|NULL |NULL |NULL |Eve |
|NULL |NULL |NULL |Jenny |
|NULL |NULL |NULL |Ketty |
我如何以将 NULL 值推到底部的方式按字母顺序排列每一列,如下所示:
|Name1 |Name2 | Name3 | Name4|
|------+------+-------+------|
|Julia |Ashley|Jane |Eve |
|Zoe |Belvet|Mark |Jenny |
|NULL |Maria |NULL |Ketty |
?
你似乎想要的是一些相当不寻常的东西(至少从我的角度来看),其中row的概念不再重要,你只关心columns,而忽略它的值来自哪一行。这有点棘手,因为 SQL 将列和行一起理解。所以你需要以某种方式解构你的表并在以后重建它们。
我们要做的第一件事是有一个不同
table
的(子查询的结果)有两列: arow_number()
和 oneNameX
:对于每一列,我们将执行以下操作:
...这将导致:
这是一种解构(给它一个名字)。
注意:
@rownum := @rownum + 1
等同于ROW_NUMBER()
在标准 SQL 中使用。请参阅MySQL 中的 ROW_NUMBER()。MySQL 没有row_number()
函数,但允许您在查询中使用变量(参见MySQL 5.7 参考手册/语言结构/用户定义变量/9.4 用户定义变量)考虑到这一点,我们需要做的是:
rank
) 并且行数与原始表相同。我们JOIN
将他们放在这个公共专栏中。NULL
端到端的行WHERE NOT (Name1 IS NULL AND Name2 IS NULL AND Name3 IS NULL AND Name4 IS NULL)
完整的查询将是:
这将为您提供预期的结果:
您可以在dbfiddle此处一起检查所有内容
如果您使用的是 MariaDB 10.2 或其他了解
WINDOW
函数的数据库,则可以将此查询简化为:你会得到相同的结果。
dbfiddle在这里
您甚至可以发挥 MariaDB 排序这一事实的优势
NULLS LAST
,而忽略COALESCE
:dbfiddle在这里
注意:执行计划是相同的,因此最后两个查询预计将花费大约相同的时间来执行。