[英]Postgres Conditional Select?
I'm not really sure how to describe this problem without an example, so here's an example: 我不太确定如何在没有示例的情况下描述此问题,所以这里有一个示例:
I have three tables: 我有三个表:
Table 1: Boxes 表1:盒子
BoxID | Box Name | Box Cost
1 | Bob's Box | $20
2 | Matt's Box | $21
3 | Jacob's Box | $22
4 | Beth's Box | $23
5 | Rachel's Box | $24
Table 2: Box_ProcessIDs 表2:Box_ProcessID
BoxID | ParentProcessID
1 | 123
2 | 456
3 | 789
4 | 012
5 | 234
Table 3: Box_Processes 表3:Box_Processes
ParentProcess | ChildProcess | Start Time | End Time | ProcessName
123 | AAA | 1:00 | 1:05 | Invoiced
123 | AAB | 1:30 | 1:35 | Packed
123 | BBB | 2:00 | 2:05 | Shipped
456 | CDD | 3:15 | 3:20 | Invoiced
456 | DDD | 3:25 | 3:30 | Packaging_Complete
456 | CCD | 3:35 | 3:40 | Shipped
789 | EEE | 4:15 | 4:20 | Invoiced
789 | EEF | 4:25 | 4:30 | Done_Packing
789 | EFF | 4:35 | 4:40 | Shipped
I want the output columns to be: Box Name, Box Cost, Box Shipping Duration, Box Packing Duration, Box Invoice Duration 我希望输出列为:框名称,框成本,框运输持续时间,框包装持续时间,框发票持续时间
I know I can use like %pack% to select my packing fields, and I can figure out how to use Date_Part or somesuch to get my durations, but I'm at a loss as to how to get my shipping duration
, packing duration
, and invoice duration
into separate fields. 我知道我可以像%pack%一样选择包装字段,并且可以弄清楚如何使用Date_Part或类似的方法来获取工期,但是我对如何获取
shipping duration
, packing duration
,和invoice duration
到单独的字段中。
So you want to do something like this pseudo-sql? 因此,您想执行类似此伪sql的操作吗?
select b.box_name, b.box_cost,
bp2.end_time - bp2.start_time as box_shipping_duration,
bp3.end_time - bp3.start_time as box_packing_duration,
bp1.end_time - bp1.start_time as box_invoice_duration
from boxes b
join box_processids bpid on b.boxid = bpid.boxid
left outer join box_processes bp1 on bpid.parentprocessid = bp1.parentprocess
and processname = 'Invoiced'
left outer join box_processes bp2 on bpid.parentprocessid = bp2.parentprocess
and processname = 'Shipped'
left outer join box_processes bp3 on bpid.parentprocessid = bp3.parentprocess
and processname = 'Packed'
(will need null checks, proper datetime handling, better names and so on) (将需要空检查,正确的日期时间处理,更好的名称等)
First off, your design is flawed. 首先,您的设计存在缺陷。
time
is no good for this purpose. time
对于这个目的没有好处。 It breaks as soon as you cross midnight. 越过午夜,它就会中断。 Use
timestamp
or timestamptz
instead. 请改用
timestamp
或timestamptz
。
Next, since unquoted identifiers are cast to lower case automatically in PostgreSQL, your naming convention is no good either. 接下来,由于在PostgreSQL中无引号的标识符会自动转换为小写,因此您的命名约定也不好。 I adapted it to something more useful.
我将其修改为更有用的内容。
CREATE TABLE boxes (box_id int PRIMARY KEY, box_name text, box_cost numeric);
INSERT INTO boxes VALUES
(1, 'Bob''s Box', 20)
,(2, 'Matt''s Box', 21)
,(3, 'Jacob''s Box', 22)
,(4, 'Beth''s Box', 23)
,(5, 'Rachel''s Box', 24);
CREATE TABLE box_processids (
box_id int
,parentprocess_id int
,PRIMARY KEY(box_id, parentprocess_id)
);
INSERT INTO box_processids VALUES
(1, 123)
,(2, 456)
,(3, 789)
,(4, 012)
,(5, 234);
CREATE TABLE box_processes (
parentprocess_id int
,childprocess_id char(3)
,start_time timestamp
,end_time timestamp
,processname text
,PRIMARY KEY(parentprocess_id, childprocess_id)
);
INSERT INTO box_processes VALUES
(123, 'AAA', '2013-2-10 1:00', '2013-2-10 1:05', 'Invoiced')
,(123, 'AAB', '2013-2-10 1:30', '2013-2-10 1:35', 'Packed')
,(123, 'BBB', '2013-2-10 2:00', '2013-2-10 2:05', 'Shipped')
,(456, 'CDD', '2013-2-10 3:15', '2013-2-10 3:20', 'Invoiced')
,(456, 'DDD', '2013-2-10 3:25', '2013-2-10 3:30', 'Packaging_Complete')
,(456, 'CCD', '2013-2-10 3:35', '2013-2-10 3:40', 'Shipped')
,(789, 'EEE', '2013-2-10 4:15', '2013-2-10 4:20', 'Invoiced')
,(789, 'EEF', '2013-2-10 4:25', '2013-2-10 4:30', 'Done_Packing')
,(789, 'EFF', '2013-2-10 4:35', '2013-2-10 4:40', 'Shipped');
Your query could then look like this: 您的查询如下所示:
SELECT b.box_name
,b.box_cost
,(i.end_time - i.start_time) AS box_invoice_duration
,(p.end_time - p.start_time) AS box_packing_duration
,(s.end_time - s.start_time) AS box_shipping_duration
FROM boxes b
LEFT JOIN box_processids bp USING (box_id)
LEFT JOIN box_processes i ON i.parentprocess_id = bp.parentprocess_id
AND i.processname = 'Invoiced'
LEFT JOIN box_processes p ON i.parentprocess_id = bp.parentprocess_id
AND p.processname = 'Packed'
LEFT JOIN box_processes s ON i.parentprocess_id = bp.parentprocess_id
AND s.processname = 'Shipped'
->sqlfiddle - > sqlfiddle
Use to_char()
to format your interval
any way you want. 使用
to_char()
以任意方式设置interval
格式。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.