这个问题很难描述,特别是在标题中。或许更容易展示我想要实现的目标。这是一个Oracle数据库。
给出以下DDL(http://sqlfiddle.com/#!4/e0730):
CREATE TABLE TEST_LIST(CONTRACT VARCHAR2(10), RECEIPT_CITY VARCHAR2(15), DELIVERY_CITY VARCHAR2(15));
INSERT INTO TEST_LIST VALUES ('CTR_01', 'DETROIT', '');
INSERT INTO TEST_LIST VALUES ('CTR_01', 'KALAMAZOO', '');
INSERT INTO TEST_LIST VALUES ('CTR_01', '', 'KALAMAZOO');
INSERT INTO TEST_LIST VALUES ('CTR_01', '', 'MUSKEGON');
INSERT INTO TEST_LIST VALUES ('CTR_01', 'SOUTH HAVEN', '');
INSERT INTO TEST_LIST VALUES ('CTR_02', 'BATTLE CREEK', '');
INSERT INTO TEST_LIST VALUES ('CTR_02', '', 'KALAMAZOO');
我想获得以下结果:
CONTRACT CITY DIRECTION
-------- ------------ -----------
CTR_01 DETROIT RECEIPT
CTR_01 KALAMAZOO RECDEL
CTR_01 MUSKEGON DELIVERY
CTR_01 SOUTH HAVEN DELIVERY
CTR_02 BATTLE CREEK RECEIPT
CTR_02 KALAMAZOO DELIVERY
我挣扎的部分是当城市既是收据又是交付时,让它在一行显示为RECDEL。我尝试过UNION,INTERSECT和FULL OUTER JOIN的各种组合无济于事。可以使用LISTAGG吗?不确定该工作如何与多列一起使用。任何帮助将不胜感激。
答案 0 :(得分:2)
| CONTRACT | CITY | DIRECTION |
|----------|--------------|-----------|
| CTR_01 | DETROIT | RECEIPT |
| CTR_01 | KALAMAZOO | RECDEL |
| CTR_01 | MUSKEGON | DELIVERY |
| CTR_01 | SOUTH HAVEN | RECEIPT |
| CTR_02 | BATTLE CREEK | RECEIPT |
| CTR_02 | KALAMAZOO | DELIVERY |
由:
select distinct
t1.contract
, case when t1.delivery_city = t2.receipt_city then t1.delivery_city
when t1.delivery_city is not null then t1.delivery_city
when t1.receipt_city is not null then t1.receipt_city
else 'unexpected'
end as CITY
, case when t1.delivery_city = t2.receipt_city
or t1.receipt_city = t3.delivery_city then 'RECDEL'
when t1.delivery_city is not null then 'DELIVERY'
when t1.receipt_city is not null then 'RECEIPT'
else 'unexpected'
end as DIRECTION
from TEST_LIST t1
left join test_list t2
on t1.CONTRACT = t2.CONTRACT
and t1.delivery_city = t2.receipt_city
left join test_list t3
on t1.CONTRACT = t3.CONTRACT
and t1.receipt_city = t3.delivery_city
order by
t1.contract
, CITY
, DIRECTION
答案 1 :(得分:1)
可能有一种更清洁的方式,但这有效:
SELECT contract, receipt_city AS city, 'RECEIPT' as direction from test_list t1 where receipt_city IS NOT NULL AND NOT EXISTS (SELECT * FROM test_list t2 WHERE t2.contract = t1.contract and t2.delivery_city = t1.receipt_city )
UNION
SELECT contract, receipt_city AS city, 'RECDEL' as direction from test_list t1 where receipt_city IS NOT NULL AND EXISTS (SELECT * FROM test_list t2 WHERE t2.contract = t1.contract and t2.delivery_city = t1.receipt_city )
UNION
SELECT contract, delivery_city AS city, 'DELIVERY' as direction from test_list t1 where delivery_city IS NOT NULL AND NOT EXISTS (SELECT * FROM test_list t2 WHERE t2.contract = t1.contract and t2.receipt_city = t1.delivery_city )
ORDER BY contract;
答案 2 :(得分:1)
这是LISTAGG
的解决方案。它会生成Delivery Receipt
而不是RECDEL
。我希望你能够理解这一点。
SELECT contract,
COALESCE(receipt_city, delivery_city, '') "City",
LISTAGG(CASE WHEN receipt_city IS NOT NULL THEN 'Receipt' END ||
CASE WHEN delivery_city IS NOT NULL THEN 'Delivery' END,
' ')
WITHIN GROUP (ORDER BY contract) "Direction"
FROM test_list
GROUP BY contract, COALESCE(receipt_city, delivery_city, '');