如何连接 Postgres SELECT 中的列?

Posted

技术标签:

【中文标题】如何连接 Postgres SELECT 中的列?【英文标题】:How to concatenate columns in a Postgres SELECT? 【发布时间】:2013-11-25 09:46:50 【问题描述】:

我在表foo 中有两个字符串列ab

select a, b from foo 返回值 ab。但是,ab 的串联不起作用。我试过了:

select a || b from foo

select  a||', '||b from foo

来自 cmets 的更新:两列都是 character(2) 类型。

【问题讨论】:

... 或其他 text 类型? @acfrancis 因为 OP 说 concatenate 我怀疑他正在处理数字类型,尽管 PostgreSQL 也会处理其中的一些。见这里:postgresql.org/docs/9.1/static/functions-string.html 是的,这些列是字符 (2)。 “+”不起作用 - “没有运算符匹配给定的名称和参数类型。您可能需要添加显式类型转换。” 什么版本的 PostgreSQL?以下是 9.1 的文档:postgresql.org/docs/9.1/static/functions-string.html。看我的例子:sqlfiddle.com/#!15/d41d8/182 您的查询中可能存在与串联无关的语法错误。 【参考方案1】:

对于像character(2) 这样的string type 列(正如您稍后提到的),显示的串联只是有效,因为quoting the manual:

[...] 字符串连接运算符 (||) 接受非字符串 输入,只要至少有一个输入是字符串类型,如图所示 Table 9.8。对于其他情况,将显式强制插入text [...]

我的大胆强调。第二个示例 (select a||', '||b from foo) 适用于 any 数据类型,因为无类型字符串文字 ', ' 默认为类型 text,使得整个表达式在任何情况下都有效。

对于非字符串数据类型,您可以通过casting 至少将一个参数“修复”第一条语句到text。 (任何类型都可以转换为text):

SELECT a::text || b AS ab FROM foo;

从your own answer 判断,“不起作用”应该意味着“返回 NULL”。 anything 连接到 NULL 的结果是 NULL。如果可能涉及 NULL 值且结果不应为 NULL,请使用 concat_ws() 连接任意数量的值(Postgres 9.1 或更高版本):

SELECT concat_ws(', ', a, b) AS ab FROM foo;

仅在非空值之间添加分隔符,即仅在必要时添加。

或者 concat() 如果您不需要分隔符:

SELECT concat(a, b) AS ab FROM foo;

这里不需要类型转换,因为这两个函数都接受 "any" 输入并使用文本表示。

此相关答案中的更多详细信息(以及为什么 COALESCE 是一个糟糕的替代品):

Combine two columns and add into one new column

关于comment中的更新

+ 不是 Postgres(或标准 SQL)中字符串连接的有效运算符。将此添加到他们的产品中是 Microsoft 的私人想法。

几乎没有任何充分的理由使用 character(n)(同义词:char(n))。使用text or varchar。详情:

Any downsides of using data type "text" for storing strings? Best way to check for "empty or null value"

【讨论】:

谢谢。第一个版本不适用于 null,第二个版本给了我 concat_ws 的错误:没有函数与给定的名称和参数类型匹配。您可能需要添加显式类型转换。 你确实看到了Postgres 9.1 or later,对吧? 在问题中,您应该首先提供您的 Postgres 版本。请更新您的问题与所有要求的信息,然后再回来做其他事情。 谢谢,我找到的解决方案适用于任何 Postgres 版本abVARCHARs 时,SELECT concat(a, b) FROM foo; 在 Postgres 9.3 中为我工作。【参考方案2】:

问题在于值中的空值;那么连接不适用于空值。解决方法如下:

SELECT coalesce(a, '') || coalesce(b, '') FROM foo;

【讨论】:

【参考方案3】:

最好在PostgreSQL中使用CONCAT函数进行连接

例如:select CONCAT(first_name,last_name) from person where pid = 136

如果您使用的是 column_a || ' ' || column_b 用于连接 2 列,如果 column_a 或 column_b 中的任何值为空,查询将返回空值。 这可能不是在所有情况下都是首选的.. 所以而不是这个

||

使用

连接

如果它们中的任何一个具有值,它将返回相关值

【讨论】:

为我工作。高兴地发现我也可以在两者之间添加一个空格:CONCAT(first_name, ' ', last_name) 这应该是正确的答案,因为 concat 接受 null【参考方案4】:

CONCAT 函数有时不适用于旧的 postgreSQL 版本

看看我过去在不使用 CONCAT 的情况下解决问题的方法

 u.first_name || ' ' || u.last_name as user,

或者你也可以使用

 "first_name" || ' ' || "last_name" as user,

在第二种情况下,我为 first_name 和 last_name 使用了双引号

希望对你有用,谢谢

【讨论】:

如果我的名字或姓氏为 null,则 concat 值也显示为 null【参考方案5】:

由于我也陷入了困境,我认为我应该分享最适合我的解决方案。我也认为这要简单得多。

如果您使用大写的表名。

SELECT CONCAT("firstName", ' ', "lastName") FROM "User"

如果你使用小写的表名

SELECT CONCAT(firstName, ' ', lastName) FROM user

就是这样!由于 PGSQL 计算列声明的双引号和字符串的单引号,这就像一个魅力。

【讨论】:

如果可以有 NULL 值,这个表达式会产生一个前导或尾随空格。通常不是你想要的。请改用concat_ws()【参考方案6】:

PHP 的 Laravel 框架, 我正在使用搜索 first_name, last_name 字段被视为全名搜索

使用 || symbol 或 concat_ws()、concat() 方法

$names = str_replace(" ", "", $searchKey);                               
$customers = Customer::where('organization_id',$this->user->organization_id)
             ->where(function ($q) use ($searchKey, $names) 
                 $q->orWhere('phone_number', 'ilike', "%$searchKey%"); 
                 $q->orWhere('email', 'ilike', "%$searchKey%");
                 $q->orWhereRaw('(first_name || last_name) LIKE ? ', '%' . $names. '%');
    )->orderBy('created_at','desc')->paginate(20);

这很有魅力!!!

【讨论】:

【参考方案7】:

试试这个

select textcat(textcat(FirstName,' '),LastName) AS Name from person;

【讨论】:

concat_ws(' ', FirstName, LastName) 会干净得多。【参考方案8】:

例如,如果有一个包含以下列的员工表:

employee_number,f_name,l_name,email_id,phone_number 

如果我们想将f_name + l_name 连接为name

SELECT employee_number,f_name ::TEXT ||','|| l_name::TEXT  AS "NAME",email_id,phone_number,designation FROM EMPLOYEE;

【讨论】:

这个答案比现有答案添加了什么?

以上是关于如何连接 Postgres SELECT 中的列?的主要内容,如果未能解决你的问题,请参考以下文章

如何计算grafana / postgres中不同记录的列值之间的差异

如何使用pyspark将json对象插入postgres表中的列

如何使用保存在表中的水平数据作为postgres中的列

如何使用枢轴将行转换为postgres中的列?让我来计算一下

如何对具有纪元值的列进行 JOIN 查询,忽略 postgres 中的时间部分

如何使用select合并postgres中的两行[重复]