ตั้งชื่อเป็นแอตทริบิวต์เมื่อสร้าง JSON ด้วย row_to_json


24

เป็นไปได้หรือไม่ที่จะเปลี่ยนชื่อชื่อเริ่มต้นf1, f2, f3...เมื่อใช้row_to_jsonฟังก์ชั่นสำหรับบางคอลัมน์เท่านั้น?

ที่ฉันสามารถทำได้

row_to_json(customers)

การคืน

{"id_customer":2,"first_name":"bla","last_name":"second_bla"}

แต่ถ้าฉันต้องการชื่อโดยไม่มีid_customerฉันต้องใช้

row_to_json(row(first_name, last_name))

แล้วฉันจะได้รับ

{"f1":"bla","f2":"second_bla"}

และฉันต้องการรับผลลัพธ์นี้ด้วยชื่อคอลัมน์เริ่มต้นหรือของฉันเอง ฉันรู้ว่าฉันสามารถสร้างประเภทคอมโพสิตและการใช้งานของฉันเอง

row_to_json(row(first_name, last_name))::my_custom_type

แต่เป็นไปไม่ได้ไหมที่จะทำให้ถูกต้องในแบบสอบถามโดยไม่ต้องสร้างประเภทนั้น


1
ดูได้ที่: การอ้างอิง 1และการอ้างอิง 2สำหรับสิ่งที่คล้ายกัน
MikeM

คำตอบ:


17

นิพจน์ตารางทั่วไปช่วยให้คุณระบุนามแฝงอย่างชัดเจนไม่เพียง แต่สำหรับ CTE แต่สำหรับคอลัมน์

WITH data(col1,col2,cola,colb) AS (
  VALUES (1,2,'fred','bob')
)
SELECT row_to_json(data) FROM data;

สิ่งนี้แตกต่างจากตัวอย่างของ @ dezso ซึ่งไม่ได้ใช้col AS aliasสำหรับแต่ละคอลัมน์ในSELECTรายการ มันใช้นามแฝงชื่อคอลัมน์ในนามแฝงตาราง CTE

ฉันใช้VALUESนิพจน์เป็นแบบสอบถามย่อย แต่คุณสามารถใช้SELECTสิ่งที่คุณต้องการ; ประเด็นก็คือสิ่งที่คอลัมน์นามแฝงมีให้หรือสันนิษฐานในแบบสอบถามย่อยสามารถแทนที่ในคำนิยาม CTE โดยการระบุคอลัมน์ชื่อรายการ

คุณสามารถทำสิ่งเดียวกันได้ในแบบสอบถามย่อยอีกครั้งแทนที่จะใช้AS alias:

SELECT row_to_json(data) 
FROM (VALUES (1,2,'fred','bob')) data(col1,col2,cola,colb);

วิธีนี้ใช้ไม่ได้กับROWนิพจน์โดยตรง คุณสามารถส่งเป็นROWรูปธรรมได้เท่านั้นคุณไม่สามารถใช้นามแฝงได้

regress=> SELECT ROW(1,2,'fred','bob') AS x(a,b,c,d);
ERROR:  syntax error at or near "("
LINE 1: SELECT ROW(1,2,'fred','bob') AS x(a,b,c,d);

มีความแตกต่าง (นอกเหนือจากสไตล์และ / หรือความสามารถในการอ่าน) ระหว่างโซลูชันของเรา (การใช้งานประสิทธิภาพ ฯลฯ ) หรือไม่?
dezso

@dezso ไม่และฉันอาจจะเพิ่งโพสต์ความคิดเห็น ขอโทษ
Craig Ringer

ฉันคิดว่ามันโอเค ฉันยัง upvote คำตอบของคุณ b / c มันมีข้อมูลที่เป็นประโยชน์ซึ่งฉันไม่ได้
dezso

มีไวยากรณ์สำหรับรับชื่อแทนคอลัมน์แบบไดนามิกหรือไม่? ฉันกำลังดึงจากสกีมา EAV (ค่าแอตทริบิวต์เอนทิตี) ที่ชื่อคีย์ที่ต้องการถูกเลือกจากคอลัมน์ attribute.name
Chris

@Chris คุณจะต้องใช้ฟังก์ชัน json ที่ซับซ้อนยิ่งขึ้นใน 9.4
Craig Ringer

23
select 
   c.id,
   (select row_to_json(_) from (select c.first_name, c.last_name) as _) as first_last,
   c.age
from
   customers as c

จะทำสิ่งที่คุณต้องการโดยไม่มีผลกระทบต่อประสิทธิภาพ (และไม่มากเกินไป):

  id  |   first_last                                |   age
------+---------------------------------------------+---------
  1   | {"fisrt_name": "John", "last_name": "Smit"} |   34

4
คำตอบนี้เป็นอัญมณี
tiffon

ขอบคุณมากที่คุณบันทึกช่วงบ่ายของฉันแย่เกินไปนี่ไม่ใช่ตัวอย่างที่อ้างถึงใน PostgreSQL API ฉันรู้ว่ามันเป็นไปได้
jlandercy

9

คุณสามารถทำสิ่งนี้:

WITH r AS (
  SELECT 'bla' AS name1, 'otherbla' AS name2
)
SELECT row_to_json(r.*)
FROM r
;

(แน่นอนเดียวกันสามารถทำได้ด้วย

SELECT row_to_json(r.*)
FROM (SELECT 'bla' AS name1, 'otherbla' AS name2) r
;

แต่ฉันพบว่าอดีตอ่านได้มากขึ้น)

ในWITHส่วนที่คุณสามารถสร้างแถวของโครงสร้างใด ๆ ได้ทันที


ในการต่อเชื่อม non-jsonb กับ jsonb :: SELECT row_to_json (r. *) FROM (SELECT c1, c2 :: jsonb จาก us_ca_monterey_aoc.test) เป็น r
Andrew Scott Evans

9

json_build_objectคุณสามารถใช้

SELECT 
  json_build_object('id', data.customer_id, 'first_name', data.first_name, 'last_name', data.last_name) as your_json
FROM data;
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.