未实现匿名复合类型的输入-Postgres

kis*_*ore 1 sql postgresql

我有一个带有XML列的表。XML可以包含一个可选的link元素。

<Link ReasonCode="MultiLabel">
  <UUID>1d177dee-1da4-4451-b175-396666afc370</UUID>
</Link>
Run Code Online (Sandbox Code Playgroud)

我想从表中获取没有链接元素的所有记录。从那些具有link元素的记录中,我只希望获取DISTINCT记录。如果两个记录具有相同的链接元素,请跳过第二个记录。我尝试过的查询

SELECT DISTINCT cast((xpath('/Data/Link', xmldata)) AS TEXT) 
FROM tblData AS link 
WHERE link != '{}'
Run Code Online (Sandbox Code Playgroud)

错误:未实现匿名复合类型的输入

  1. 我在这里做错了什么导致上述错误?没有WHERE子句的查询工作正常。
  2. 除此之外,我想在该DISTINCT方法开始处理结果之前使用order by子句。再次,我弄乱了使用order by和distinct一起使用的语法,但出现错误。

如何针对该查询基于表中列的值实现结果的排序?

a_h*_*ame 5

在表达式中link != '{}',别名link引用,而不是单个列(由于tblData AS link)。

Postgres允许通过使用表名(或表别名)来引用表的完整行。该错误告诉您无法将完整的行与单个数组值进行比较。

您需要这样的东西:

select distinct cast(xpath('/Data/Link', xmldata) AS TEXT) as linkdata
from data 
where cast(xpath('/Data/Link', xmldata) AS TEXT) <> '{}';
Run Code Online (Sandbox Code Playgroud)

不幸的是,在where子句中不能使用列别名。如果要避免重复该表达式,请使用派生表:

select distinct linkdata 
from (
  select cast(xpath('/Data/Link', xmldata) AS TEXT) as linkdata
  from data 
) t 
where linkdata <> '{}';
Run Code Online (Sandbox Code Playgroud)

但正如你只期待一个链接无论如何,下面可能更好:

select distinct linkdata 
from (
  select (xpath('/Data/Link', xmldata))[1] as linkdata
  from data 
) t 
where linkdata is not null;
Run Code Online (Sandbox Code Playgroud)

xpath()返回一个数组,表达式(xpath(..))[1]获取该数组的第一个元素,如果没有这样的元素,则返回null。也许您xpath('/Data/Link/UUID/text()')只是想获取实际的UUID,而不是完整的XML节点-但这在您提供的示例中还不清楚。