ติดตั้งโมดูลเพิ่มเติมtablefunc
ครั้งเดียวcrosstab()
ต่อฐานข้อมูลซึ่งมีฟังก์ชั่น ตั้งแต่ Postgres 9.1 คุณสามารถใช้CREATE EXTENSION
เพื่อ:
CREATE EXTENSION IF NOT EXISTS tablefunc;
ปรับปรุงกรณีทดสอบ
CREATE TABLE tbl (
section text
, status text
, ct integer -- "count" is a reserved word in standard SQL
);
INSERT INTO tbl VALUES
('A', 'Active', 1), ('A', 'Inactive', 2)
, ('B', 'Active', 4), ('B', 'Inactive', 5)
, ('C', 'Inactive', 7); -- ('C', 'Active') is missing
รูปแบบเรียบง่าย - ไม่เหมาะกับแอตทริบิวต์ที่ขาดหายไป
crosstab(text)
ด้วย1อินพุตพารามิเตอร์:
SELECT *
FROM crosstab(
'SELECT section, status, ct
FROM tbl
ORDER BY 1,2' -- needs to be "ORDER BY 1,2" here
) AS ct ("Section" text, "Active" int, "Inactive" int);
ผลตอบแทน:
มาตรา | ใช้งานอยู่ | เฉื่อยชา
--------- + -------- + ----------
A | 1 | 2
B | 4 | 5
C | 7 | - !!
- ไม่จำเป็นต้องหล่อและเปลี่ยนชื่อ
- สังเกตผลลัพธ์ที่ไม่ถูกต้องสำหรับ
C
: ค่า7
ถูกป้อนสำหรับคอลัมน์แรก บางครั้งพฤติกรรมนี้เป็นที่ต้องการ แต่ไม่ใช่สำหรับกรณีการใช้งานนี้
- รูปแบบที่เรียบง่ายนอกจากนี้ยังถูก จำกัด ไว้ที่ตรงสามคอลัมน์ในแบบสอบถามสำหรับการป้อนให้: ROW_NAME , หมวดหมู่ , ค่า ไม่มีที่ว่างสำหรับคอลัมน์เพิ่มเติมเช่นในทางเลือกที่ 2 พารามิเตอร์ด้านล่าง
ฟอร์มปลอดภัย
crosstab(text, text)
ด้วย2พารามิเตอร์อินพุต:
SELECT *
FROM crosstab(
'SELECT section, status, ct
FROM tbl
ORDER BY 1,2' -- could also just be "ORDER BY 1" here
, $$VALUES ('Active'::text), ('Inactive')$$
) AS ct ("Section" text, "Active" int, "Inactive" int);
ผลตอบแทน:
มาตรา | ใช้งานอยู่ | เฉื่อยชา
--------- + -------- + ----------
A | 1 | 2
B | 4 | 5
C | | 7 - !!
C
หมายเหตุผลที่ถูกต้องสำหรับ
พารามิเตอร์ที่สองสามารถสอบถามว่าผลตอบแทนที่หนึ่งแถวต่อแอตทริบิวต์ที่ตรงกับคำสั่งของนิยามคอลัมน์ที่สิ้นสุด บ่อยครั้งที่คุณต้องการสืบค้นแอตทริบิวต์ที่แตกต่างจากตารางที่มีลักษณะดังนี้:
'SELECT DISTINCT attribute FROM tbl ORDER BY 1'
ที่อยู่ในคู่มือ
เนื่องจากคุณต้องสะกดคอลัมน์ทั้งหมดในรายการนิยามคอลัมน์ต่อไป (ยกเว้นสำหรับตัวแปรที่กำหนดไว้ล่วงหน้า) ดังนั้นโดยทั่วไปจะมีประสิทธิภาพมากกว่าในการแสดงรายการสั้น ๆ ในนิพจน์ที่แสดง:crosstabN()
VALUES
$$VALUES ('Active'::text), ('Inactive')$$)
หรือ (ไม่ใช่ในคู่มือ):
$$SELECT unnest('{Active,Inactive}'::text[])$$ -- short syntax for long lists
ฉันใช้การอ้างอิงดอลลาร์เพื่อให้การอ้างง่ายขึ้น
คุณสามารถเอาท์พุทคอลัมน์ที่มีชนิดข้อมูลต่างๆด้วยcrosstab(text, text)
- ตราบใดที่การแสดงข้อความของคอลัมน์ค่าเป็นอินพุตที่ถูกต้องสำหรับประเภทเป้าหมาย วิธีนี้คุณอาจมีแอตทริบิวต์ของชนิดที่แตกต่างกันและเอาท์พุทtext
, date
, numeric
ฯลฯ สำหรับแอตทริบิวต์ที่เกี่ยวข้อง มีตัวอย่างโค้ดที่ปลายเป็นบทcrosstab(text, text)
ในคู่มือ
db <> ซอที่นี่
ตัวอย่างขั้นสูง
\crosstabview
ใน psql
Postgres 9.6เพิ่มเมตานี้สั่งไปยังสถานีของมันเริ่มต้นโต้ตอบpsql คุณสามารถเรียกใช้แบบสอบถามที่คุณจะใช้เป็นcrosstab()
พารามิเตอร์แรกและป้อนไปยัง\crosstabview
(ทันทีหรือในขั้นตอนถัดไป) ชอบ:
db=> SELECT section, status, ct FROM tbl \crosstabview
ผลลัพธ์ที่คล้ายกันข้างต้น แต่เป็นคุณลักษณะการแสดงในฝั่งไคลเอ็นต์โดยเฉพาะ แถวอินพุตจะถือว่าแตกต่างกันเล็กน้อยดังนั้นจึงORDER BY
ไม่จำเป็น รายละเอียดสำหรับ\crosstabview
ในคู่มือ มีตัวอย่างโค้ดเพิ่มเติมที่ด้านล่างของหน้านั้น
คำตอบที่เกี่ยวข้องกับ dba.SE โดย Daniel Vérité (ผู้เขียนคุณสมบัติ psql):
ตอบรับก่อนหน้านี้ล้าสมัย
ตัวแปรของฟังก์ชันcrosstab(text, integer)
นั้นล้าสมัยแล้ว integer
พารามิเตอร์ที่สองจะถูกละเว้น ฉันพูดคู่มือปัจจุบัน :
crosstab(text sql, int N)
...
crosstab(text)
รุ่นล้าสมัยของ N
ตอนนี้พารามิเตอร์จะถูกละเว้นเนื่องจากจำนวนคอลัมน์ค่าจะถูกกำหนดโดยคิวรีการโทรเสมอ
หล่อและเปลี่ยนชื่อโดยไม่จำเป็น
มันล้มเหลวหากแถวไม่มีคุณสมบัติทั้งหมด ดูตัวแปรที่ปลอดภัยที่มีพารามิเตอร์อินพุตสองตัวด้านบนเพื่อจัดการแอตทริบิวต์ที่ขาดหายไปอย่างเหมาะสม
ORDER BY
crosstab()
จะต้องอยู่ในรูปแบบหนึ่งของพารามิเตอร์ คู่มือ:
ในทางปฏิบัติแบบสอบถาม SQL ควรระบุเสมอORDER BY 1,2
เพื่อให้แน่ใจว่ามีการเรียงลำดับแถวเข้าอย่างถูกต้อง