Làm cách nào để nối các cột trong CHỌN Postgres?


145

Tôi có hai cột chuỗi abtrong một bảng foo.

select a, b from footrả về giá trị ab. Tuy nhiên, nối abkhông hoạt động. Tôi đã thử:

select a || b from foo

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

Cập nhật từ ý kiến: cả hai cột là loại character(2).


... Hoặc textloại khác ?
PM 77-1

@acfrancis Vì OP nói rằng concatenatetôi nghi ngờ rằng anh ta đang xử lý các loại số, mặc dù PostgreQuery cũng sẽ chăm sóc một số trong số họ. Xem tại đây: postgresql.org/docs/9.1/static/fifts-opes.html
PM 77-1

Vâng, các cột này là ký tự (2). "+" không hoạt động - "Không có toán tử nào khớp với tên và loại đối số đã cho. Bạn có thể cần thêm các kiểu phôi rõ ràng."
Alex

Phiên bản nào của PostgreSQL? Dưới đây là các tài liệu cho 9.1: postgresql.org/docs/9.1/static/fifts-opes.html . Xem ví dụ của tôi: sqlfiddle.com/#!15/d41d8/182
PM 77-1

Bạn có thể có một lỗi cú pháp trong truy vấn của bạn không liên quan đến ghép.
PM 77-1

Câu trả lời:


260

Với các cột kiểu chuỗi như character(2)(như bạn đã đề cập sau), phép nối được hiển thị chỉ hoạt động vì, trích dẫn hướng dẫn:

[...] Toán tử nối chuỗi ( ||) chấp nhận đầu vào không phải chuỗi, miễn là có ít nhất một đầu vào thuộc loại chuỗi , như trong Bảng 9.8 . Đối với các trường hợp khác, chèn một ép buộc rõ ràng vào text[...]

Nhấn mạnh đậm của tôi. Ví dụ thứ 2 ( select a||', '||b from foo) hoạt động cho bất kỳ loại dữ liệu nào kể từ khi ', 'mặc định chuỗi ký tự không được gõ textthành kiểu làm cho toàn bộ biểu thức hợp lệ trong mọi trường hợp.

Đối với các kiểu dữ liệu không phải chuỗi, bạn có thể "sửa" câu lệnh thứ nhất bằng cách truyền ít nhất một đối số thành text. ( Bất kỳ loại nào cũng có thể được sử dụng text):

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

Đánh giá từ câu trả lời của riêng bạn , " không hoạt động " được cho là có nghĩa là " trả về NULL ". Kết quả của bất cứ điều gì được nối với NULL là NULL. Nếu các giá trị NULL có thể được tham gia và kết quả sẽ không phải là NULL, hãy sử dụng concat_ws()để nối bất kỳ số lượng giá trị nào (Postgres 9.1 trở lên):

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

Hoặc concat()nếu bạn không cần dấu phân cách:

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

Không cần kiểu phôi ở đây vì cả hai hàm đều "any"nhập và làm việc với biểu diễn văn bản.

Thêm chi tiết (và tại sao COALESCElà người thay thế kém) trong câu trả lời liên quan này:

Về cập nhật trong bình luận

+không phải là toán tử hợp lệ cho nối chuỗi trong Postgres (hoặc SQL chuẩn). Đó là một ý tưởng riêng tư của Microsoft để thêm điều này vào các sản phẩm của họ.

Hầu như không có lý do chính đáng để sử dụng character(n)(từ đồng nghĩa char(n):). Sử dụng texthoặcvarchar . Chi tiết:


Cảm ơn bạn. Phiên bản thứ 1 không hoạt động với null và phiên bản thứ 2 gây ra lỗi cho concat_ws: Không có chức năng nào khớp với tên và loại đối số đã cho. Bạn có thể cần thêm phôi loại rõ ràng.
Alex

1
Bạn đã thấy Postgres 9.1 or later, phải không? Bạn nên cung cấp phiên bản Postgres của bạn để bắt đầu, trong câu hỏi . Vui lòng cập nhật câu hỏi của bạn với tất cả các thông tin được yêu cầu, trước khi bạn quay lại cho bất cứ điều gì khác.
Erwin Brandstetter

Cảm ơn bạn, giải pháp tôi tìm thấy hoạt động cho mọi phiên bản Postgres
Alex

SELECT concat(a, b) FROM foo;làm việc cho tôi trong Postgres 9.3 khi abVARCHARs.
Elimisteve 3/2/2015

Cảm ơn câu trả lời của bạn, nó đã giải quyết vấn đề của tôi :).
ashwaqar

33

Vấn đề là null trong các giá trị; sau đó nối không hoạt động với null. Giải pháp như sau:

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

18

tốt hơn là sử dụng hàm CONCAT trong PostgreSQL để ghép nối

ví dụ : select CONCAT(first_name,last_name) from person where pid = 136

nếu bạn đang sử dụng cột_a | | '' || cột_b để ghép cho 2 cột, nếu bất kỳ giá trị nào trong cột_a hoặc cột_b là truy vấn null sẽ trả về giá trị null. mà có thể không được ưa thích trong mọi trường hợp .. vì vậy thay vì điều này

| |

sử dụng

Ý TƯỞNG

nó sẽ trả về giá trị liên quan nếu một trong hai có giá trị


7

Các hàm CONCAT đôi khi không hoạt động với phiên bản postgreSQL cũ hơn

xem những gì tôi đã sử dụng để giải quyết vấn đề mà không cần sử dụng CONCAT

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

Hoặc bạn cũng có thể sử dụng

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

trong trường hợp thứ hai, tôi đã sử dụng dấu ngoặc kép cho First_name và last_name

Hy vọng điều này sẽ hữu ích, cảm ơn


1
nếu tên hoặc họ của tôi là null thì giá trị concat cũng hiển thị null
Lokesh

2

Vì tôi cũng bị mắc kẹt trong việc này, nghĩ rằng tôi nên chia sẻ giải pháp phù hợp nhất với mình. Tôi cũng nghĩ rằng điều này đơn giản hơn nhiều.

Nếu bạn sử dụng tên bảng viết hoa.

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

Nếu bạn sử dụng tên bảng chữ thường

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

Đó là nó!. Vì PGQuery tính Double Trích dẫn cho khai báo cột và Trích dẫn đơn cho chuỗi, điều này hoạt động như một nét duyên dáng.


1

Khung công tác Laravel của PHP, tôi đang sử dụng tìm kiếm First_name, Last_name Trường xem xét như Tìm kiếm tên đầy đủ

Sử dụng | | biểu tượng Hoặc phương thức 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);

Điều này làm việc say mê !!!



-1

Ví dụ: nếu có bảng nhân viên bao gồm các cột như:

employee_number,f_name,l_name,email_id,phone_number 

nếu chúng ta muốn nối f_name + l_namenhư name.

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

Câu trả lời này thêm gì vào câu trả lời hiện có?
Erwin Brandstetter
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.