从case语句解压缩表达式结果

问题描述 投票:0回答:1

类别表中的四个类别。

id | name
--------------
1  | 'wine'
2  | 'chocolate'
3  | 'autos'
4  | 'real estate'

预报员表中的众多(数千名)预报员中的两位。

id | name
--------------
1  | 'sothebys'
2  | 'cramer'

预报员对预测表中类别的相关预测。

| id | forecaster_id | category_id | forecast                                                     |
|----+---------------+-------------+--------------------------------------------------------------|
|  1 |             1 |           1 | 'bad weather, prices rise short-term'                        |
|  2 |             1 |           2 | 'cocoa bean surplus, prices drop'                            |
|  3 |             1 |           3 | 'we dont deal with autos - no idea'                          |
|  4 |             2 |           2 | 'sell, sell, sell'                                           |
|  5 |             2 |           3 | 'demand for cocoa will skyrocket - prices up - buy, buy buy' |

我想要(预测者,类别,预测)的优先级映射,如果某个主要预测者(例如“疯子”)的预测存在,请使用它,因为我更信任他。如果对某些二级预报员(例如'sothebys')有预测,则使用该预测。如果类别没有预测,则返回具有该类别的行,并返回null以进行预测。

我有一些几乎可以工作的东西,在我得到逻辑后我希望变成参数化查询。

select
    case when F1.category is not null
        then (F1.forecaster, F1.category, F1.forecast)
    when F2.category is not null 
        then (F2.forecaster, F2.category, F2.forecast)
    else (null, C.category, null)
    end
from 
    (
        select 
                FR.name as forecaster, 
                C.id as cid, 
                C.category as category, 
                F.forecast 
        from 
                forecast F 
                inner join forecaster FR on (F.forecaster_id = FR.id)  
                inner join category C on (C.id = F.category_id)
        where FR.name = 'cramer'
    ) F1
        right join (
        select 
                FR.name as forecaster, 
                C.id as cid, 
                C.category as category, 
                F.forecast  
        from 
            forecast F 
            inner join forecaster FR on (F.forecaster_id = FR.id)  
            inner join category C on (C.id = F.category_id)
        where FR.name = 'sothebys'
    ) F2 on (F1.cid = F2.cid)
    full outer join category C on (C.id = F2.cid);

这给出了:

'(sothebys,wine,"bad weather, prices rise short-term")'
'(cramer,chocolate,"sell, sell, sell")'
'(cramer,autos,"demand for cocoa will skyrocket - prices up - buy, buy buy")'
'(,"real estate",)'

虽然这是所需的数据,但它是一列而不是三列的记录。 case是我能找到的唯一方式来实现cramer排序第一次sothebys接下来有很多重复。有没有更好的方法,如何将元组结果拉回到列中?

任何建议,特别是与删除重复或一般简化有关的建议表示赞赏。

postgresql case
1个回答
2
投票

这听起来像是DISTINCT ON(未经测试)的情况:

SELECT DISTINCT ON (c.id)
       fr.name AS forecaster,
       c.name AS category,
       f.forecast
FROM forecast f 
   JOIN forecaster fr ON f.forecaster_id = fr.id
   RIGHT JOIN category c ON f.category_id = c.id
ORDER BY 
   c.id, 
   CASE WHEN fr.name = 'cramer'   THEN 0 
        WHEN fr.name = 'sothebys' THEN 1
        ELSE 2 
   END;

对于每个类别,将选择订购中的第一行。由于Cramer的id比苏富比更高,因此会优先考虑。

如果您需要更复杂的排名,请调整ORDER BY子句。

© www.soinside.com 2019 - 2024. All rights reserved.