【问题标题】:Coalesce equivalent for nth not null value - MySQL第 n 个非空值的合并等效项 - MySQL
【发布时间】:2020-11-20 12:15:32
【问题描述】:

我一直在为这个问题而烦恼。我正在使用现有数据集,需要从表 A 中的列中删除所有空值并将它们分流,以便它们像表 B 中一样排序

我需要一些与 Coalesce 等效的东西,但要检索第 n 个值,以便我可以得到像表 B 中那样排序的结果

我有什么:

表 A

Name CURRENT OCT12 SEPT12 AUG12 JUL12 JUN12  MAY12 APR12
---------------------------------------------------------
A    NULL    NULL  Aug-12 NULL  NULL  Jun-12 NULL  Apr-12
B    Nov-12  NULL  Aug-12 NULL  Jul-12Jun-12 NULL  Apr-12

我需要什么:

表 B

Name Change1 Change2 Change3 Change4 Change5 Change6
----------------------------------------------------
A    Aug-12  Jun-12  Apr-12  NULL    NULL    NULL   
B    Nov-12  Aug-12  Jul-12  Jun-12  Apr-12  NULL

在代码方面,它会是这样的:

Select

first non-null value as Change1  
,second non-null value as Change2  
,third non-null value as Change3  
,fourth non-null value as Change4  
,fifth non-null value as Change5...etc..  

from Table_A

我正在使用 MySQL,但我不知道如何引用第 n 个非 null 值以便将它们调用到 Table_B 中

有人有什么想法吗?

【问题讨论】:

  • 也许您也应该显示您的查询。很难理解你想要什么。
  • 这是否意味着将每个月放在一行而不是在列中?麻烦的是,在这种情况下,每个不同的月份都来自不同的源表。我的问题可能是我习惯于查询数据库中的代码,但我从来没有从头开始设计数据库,所以我的技能在这方面受到了影响:(
  • 我没有查询来获取数据,这就是我需要的。我可以使用 Coalesce 将表 A 中的第一个非空值拉到表 B 中的 Change1 列中,我可以使用复杂的 case 语句将表 A 中的第二个非空值检索到表 B 中。我的问题出现在尝试时要检索第 3、4、5 个非空值,我想不出用于将这些从表 A 提取到表 B 中的代码...

标签: mysql


【解决方案1】:

我不确定我是否会推荐使用此解决方案...对您的数据进行规范化总是一个更好的选择,但我想使用带有一些字符串函数的普通 SQL 来回答。此查询应返回您要查找的内容:

SELECT
  Name,
  Changes,
  REVERSE(SUBSTRING_INDEX(REVERSE(SUBSTRING_INDEX(Changes, ',', 1)), ',', 1)) as Change1,
  REVERSE(SUBSTRING_INDEX(REVERSE(SUBSTRING_INDEX(Changes, ',', 2)), ',', 1)) as Change2,
  REVERSE(SUBSTRING_INDEX(REVERSE(SUBSTRING_INDEX(Changes, ',', 3)), ',', 1)) as Change3,
  REVERSE(SUBSTRING_INDEX(REVERSE(SUBSTRING_INDEX(Changes, ',', 4)), ',', 1)) as Change4,
  REVERSE(SUBSTRING_INDEX(REVERSE(SUBSTRING_INDEX(Changes, ',', 5)), ',', 1)) as Change5,
  REVERSE(SUBSTRING_INDEX(REVERSE(SUBSTRING_INDEX(Changes, ',', 6)), ',', 1)) as Change6
FROM (
  SELECT
    Name,
    CONCAT_WS(',', CURRENT, OCT12, SEPT12, AUG12, JUL12, JUN12, MAY12, APR12, ',') as Changes
  FROM
    TableA
) s

我将所有值连接在一个逗号分隔的字符串中,字符串末尾有两个逗号(一个逗号就足够了,但是放两个更容易忽略最后一个...),并且由于我使用的是 CONCAT_WS,它会自动跳过空值,并且生成的字符串将类似于 Aug-12,Jun-12,Apr-12,,

然后在外部查询中,我使用 SUBSTRIG_INDEX 提取字符串的第 n 个元素。我建议标准化您的数据库,但如果您需要快速修复,此解决方案可能是一个很好的起点。

看到它工作here

请注意,我不会在没有更改的情况下返回 NULL 值,而是返回空字符串。如果需要,可以更改。

【讨论】:

  • 此解决方案完美运行,非常感谢您的帮助!感谢您对 RE 数据库设计的建议,我以后会为自己的数据库记住它:)
【解决方案2】:

如果您不想使用字符串函数,您可以使用 unpivot 和行号分区尝试此 sql:

CREATE TABLE #TableA
  ( 
    "Name" VARCHAR(10),
    "CURRENT" VARCHAR(10),
    OCT12 VARCHAR(10),
    SEPT12 VARCHAR(10),
    AUG12 VARCHAR(10),
    JUL12 VARCHAR(10),
    JUN12 VARCHAR(10),
    MAY12 VARCHAR(10),
    APR12 VARCHAR(10)
  ) 

INSERT INTO #TableA
  ("Name", "CURRENT", OCT12, SEPT12, AUG12, JUL12, JUN12, MAY12, APR12)
VALUES
  ('A', NULL, NULL, 'Aug-12', NULL, NULL, 'Jun-12', NULL, 'Apr-12'),
  ('B', 'Nov-12', NULL, 'Aug-12', NULL, 'Jul-12', 'Jun-12', NULL, 'Apr-12')

SELECT * FROM #TableA;



Select "Name",
    Min(Case row_num When 1 Then data End) Change1,
    Min(Case row_num When 2 Then data End) Change2,
    Min(Case row_num When 3 Then data End) Change3,
    Min(Case row_num When 4 Then data End) Change4,
    Min(Case row_num When 5 Then data End) Change5,
    Min(Case row_num When 6 Then data End) Change6
From
(
    select "Name",data,DBColumnName, 
        ROW_NUMBER() OVER (PARTITION BY "Name" ORDER BY "Name") row_num 
    From #TableA
    unpivot (data for DBColumnName in ("CURRENT",OCT12,SEPT12,AUG12,JUL12,JUN12,MAY12,APR12) ) as z
) TableB
group by "Name";

参考资料:

-- TSQL Pivot without aggregate function

-- https://www.sqlservertutorial.net/sql-server-window-functions/sql-server-row_number-function/

-- https://docs.microsoft.com/en-us/sql/t-sql/queries/from-using-pivot-and-unpivot?view=sql-server-ver15

【讨论】:

    猜你喜欢
    • 2011-05-05
    • 1970-01-01
    • 1970-01-01
    • 2017-05-15
    • 2021-06-16
    • 2011-08-13
    • 1970-01-01
    • 2021-06-03
    • 2021-05-13
    相关资源
    最近更新 更多