【问题标题】:UNNEST function in MYSQL like POSTGRESQLMYSQL 中的 UNNEST 函数,如 POSTGRESQL
【发布时间】:2015-02-06 12:13:47
【问题描述】:

在 MYSQL 上是否有类似 POSTGRESQL 的“unnest”的功能?

查询(PSQL):

select unnest('{1,2,3,4}'::int[])

结果(如表格):

 int |
_____|
  1  |
_____|
  2  |
_____|
  3  |
_____|
  4  |
_____|

【问题讨论】:

  • 我当然做到了!我想选择一个像行这样的数组。下次回答有用的!
  • 这在 MySQL 中是不可能的。既不能使用内置函数,也不能编写函数来模仿这种行为。
  • @PhillipParente 如果您首先表明您为自己尝试了什么,并且如果您解释了您想要实现的目标,您将获得更好的答案/cmets。 “我没有在 [手册] 中找到任何合适的东西”,......“我正在尝试提供一组行作为字符串并希望数据库扩展它”等。在这种情况下,没有人可以(无需大量猜测)说“不,但你考虑过......”因为你没有告诉我们为什么你要这样做,你要解决的潜在问题是什么是。
  • "我想选择一个像 rows 这样的数组..." — MySQL 没有数组类型。你有什么价值观/类型;也许是一个特殊格式的字符串?
  • 我试图区分 csv 字符串列表和我在数据库中的内容。 [(csv) A B c d ] [(DATABASE) B C ] [(Result) A d ]

标签: mysql sql arrays


【解决方案1】:

简答

是的,这是可能的。从技术角度来看,您可以通过一个查询来实现。但问题是 - 很可能,您正试图将一些逻辑从应用程序传递到数据存储。数据存储旨在存储数据,而不是表示/格式化它,或者甚至对其应用一些逻辑。

是的,MySQL 没有数组数据类型,但在大多数情况下它不会成为问题,并且可以创建体系结构,从而满足这些限制。在任何情况下,即使您以某种方式实现它(如 - 见下文) - 您稍后将无法正确使用该数据,因为它只是结果集。当然,您可以存储它 - 比如说,稍后建立索引,但它又是应用程序的一项任务 - 因此创建该导入。

另外,请确保它不是 Jaywalker 的情况,因此不要存储分隔符分隔的值,然后再尝试提取它们。

长答案

从技术角度来看,您可以使用两个行集的Cartesian product 来做到这一点。然后使用一个众所周知的公式:

N = d1x101 + d2x102 + ...

因此,您将能够创建一个“全数字”表,然后对其进行迭代。那个迭代,连同 MySQL string functions,可能会导致你得到这样的结果:

SELECT 
  data 
FROM (
  SELECT 
    @next:=LOCATE(@separator,@search, @current+1) AS next, 
    SUBSTR(SUBSTR(@search, @current, @next-@current), @length+1) AS data, 
    @next:=IF(@next, @next, NULL) AS marker, 
    @current:=@next AS current 
  FROM 
    (SELECT 0 as i UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) as n1    
    CROSS JOIN 
    (SELECT 0 as i UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) as n2 
    CROSS JOIN 
    (SELECT 
       -- set your separator here:
       @separator := ',', 
       -- set your string here:
       @data      := '1,25,42,71',
       -- and do not touch here:
       @current   := 1,
       @search    := CONCAT(@separator, @data, @separator), 
       @length    := CHAR_LENGTH(@separator)) AS init
    ) AS joins 
WHERE 
  marker IS NOT NULL

对应的小提琴是here

您还应该注意:这不是一个函数。并且使用函数(我的意思是,用户使用CREATE FUNCTION 语句定义)不可能获得结果行集,因为 MySQL 中的函数无法根据定义返回结果集。但是,不能说完全不可能使用 MySQL 执行请求的转换。

但请记住:如果你能做某事,那并不意味着你应该去做。

【讨论】:

  • 谢谢@Alma Do!我试图区分 csv 字符串列表和我在数据库中的内容。 [(csv) A B c d ] [(DATABASE) B C ] [(Result) A d ]
  • “当然”(因为 0-9 之间有 2 个交叉连接),如果元素超过 100 个,这将不起作用。我想你只需要为你想要的每个 10 的幂添加一个“(SELECT 0 ...) CROSS JOIN”行。但它假设您知道数据的最大数量。
  • 您需要将更多成员添加到总和中。 3 代表 1.000,4 代表 10.000 等等(见解释)。但是,我仍然强烈反对使用这种方法。它仅显示学术兴趣
  • 当您使用 MySQL 大约 1 年并计划使用逗号分隔值的列时,很遗憾知道这一点。我真的很想念 Postgres...
  • " 数据存储的目的是存储数据,而不是表示/格式化它,或者更重要的是,对它应用一些逻辑。" 如果我​​们没有,为什么 RDBMS 会有这么大的格式化和转换能力打算用吗?这类似于建议我们应该像使用手提箱一样使用法拉利,并且只装满行李箱......RDBMS 让我们在应用程序逻辑中以声明方式而不是命令方式处理数据。
【解决方案2】:

此示例从表数据中获取所有“流行语”,以“,”分隔 逗号分隔列表中的最大值为 100

    WITH RECURSIVE num (n) AS (
      SELECT  1
      UNION ALL
      SELECT n+1 FROM num WHERE n<100 -- change this, if more than 100 elements
    )
    SELECT DISTINCT substring_index(substring_index(catchwords, ',', n), ',', -1) as value
    FROM data
    JOIN num
      ON char_length(catchwords) - char_length(replace(catchwords, ',', '')) >= n - 1

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-10
    • 2020-04-28
    • 2023-03-29
    • 2015-04-03
    • 2019-12-27
    • 2012-02-04
    相关资源
    最近更新 更多