在condtion中使用别名coalesce:coalesce(max(值为value然后值的情况)作为别名

时间:2018-04-19 12:15:52

标签: sql postgresql

我为表ad_params提供了交叉表,所以我做了:

coalesce(max(CASE when ad_params.name='model' and ad_params.value='cordova'then ad_params.value end ),NULL)要修复它,但条件是ad_params.value='cordova'无效 它会在modelcordova时显示所有结果,只显示model字段中的空白,因此我必须删除所有不在其中的字段

  ************************************************************************
  ad_media_id | ad_id  | name | timestamp| regdate | brand | fuel    |model 
   xxxxxxxxxxx   1      jack     xxxx                                cordova
   xxxxxxxxxxx   2      joe      xxxx                                cordova

   ************************************************************************

所以我必须拥有1号

coalesce(max(CASE WHEN ad_params.name='regdate' THEN ad_params.value END),NULL) AS regdate,

 select ad_media.ad_media_id
   , ad_media.ad_id
   , ads.name
   , action_states.timestamp
   , max(CASE WHEN ad_params.name = 'regdate' THEN ad_params.value END) 
    AS regdate
   , max(CASE WHEN ad_params.name = 'mileage' THEN ad_params.value END) 
     AS mileage
   , max(CASE WHEN ad_params.name = 'fuel'    THEN ad_params.value END) 
     AS fuel
   , max(CASE WHEN ad_params.name = 'brand'   THEN ad_params.value END) 
     AS brand
   , max(CASE WHEN ad_params.name = 'model'   THEN ad_params.value END) 
     AS model

 from ad_media 
 left join action_states 
 on action_states.ad_id = ad_media.ad_id
 inner join ads 
 on ads.ad_id = action_states.ad_id
 inner join ad_params 
 on  ad_params.ad_id = ad_media.ad_id
 and 
 (
    ad_params.name = 'model' 
    and  ad_params.value = 'cordoba' 
 )


   where action_states.state = 'reg'   
   and action_states.action_id = '1' 
   and action_states.timestamp::DATE BETWEEN '2018-04-17' AND '2018-04-17'
   and ads.category = '2010'   

   group by ad_media.ad_media_id
  , ad_media.ad_id
  , ads.name
  , action_states.timestamp 
  order by ad_media.ad_id;

1 个答案:

答案 0 :(得分:0)

在评论中进行讨论,因为您希望ad_id中的每个ad_paramsvalue只有一个name,我们可以重写您的代码,如下所示,轻松添加所需的过滤器:

select ad_media.ad_media_id
, ad_media.ad_id
, ads.name
, action_states.timestamp
, regdate.value AS regdate
, mileage.value AS mileage
, fuel.value AS fuel
, brand.value AS brand
, model.value AS model

from ad_media 
inner join action_states 
    on action_states.ad_id = ad_media.ad_id
inner join ads 
    on ads.ad_id = action_states.ad_id
left join ad_params as regdate --technically we could do an inner join here since we're using this in the WHERE clause now; but I'll leave as an outer join in case you need more advanced logic...
    on regdate.ad_id = ad_media.ad_id
    and regdate.name = 'regdate' 
left join ad_params as mileage
    on mileage.ad_id = ad_media.ad_id
    and mileage.name = 'mileage' 
left join ad_params as fuel
    on fuel.ad_id = ad_media.ad_id
    and fuel.name = 'fuel' 
left join ad_params as brand
    on brand.ad_id = ad_media.ad_id
    and brand.name = 'brand' 
left join ad_params as model
    on model.ad_id = ad_media.ad_id
    and model.name = 'model' 

where action_states.state = 'reg'   
and action_states.action_id = '1' 
and action_states.timestamp::DATE BETWEEN '2018-04-17' AND '2018-04-17'
and ads.category = '2010'   
and regdate.value = '2018' --your condition 

/* --this is probably no longer needed; if it is instead consider adding a `distinct`
group by ad_media.ad_media_id
, ad_media.ad_id
, ads.name
, action_states.timestamp 
order by ad_media.ad_id;
*/

如果您想要更多符合原始SQL的内容,以下内容也可以使用:

select ad_media.ad_media_id
, ad_media.ad_id
, ads.name
, action_states.timestamp
, max(CASE WHEN ad_params.name = 'regdate' THEN ad_params.value END) AS regdate
, max(CASE WHEN ad_params.name = 'mileage' THEN ad_params.value END) AS mileage
, max(CASE WHEN ad_params.name = 'fuel'    THEN ad_params.value END) AS fuel
, max(CASE WHEN ad_params.name = 'brand'   THEN ad_params.value END) AS brand
, max(CASE WHEN ad_params.name = 'model'   THEN ad_params.value END) AS model

from ad_media 
left join action_states 
    on action_states.ad_id = ad_media.ad_id
inner join ads 
    on ads.ad_id = action_states.ad_id
inner join ad_params --since we expect this filter to remove results, we now need it to be an inner join
    ad_params.ad_id = on ad_media.ad_id
    and 
    (
        ad_params.name != 'regdate' --\_i.e. if the value is regdate we want 2018; if it's not regdate we'll take any value
        or ad_params.value = '2018' --/
    )

where action_states.state = 'reg'   
and action_states.action_id = '1' 
and action_states.timestamp::DATE BETWEEN '2018-04-17' AND '2018-04-17'
and ads.category = '2010'   

group by ad_media.ad_media_id
, ad_media.ad_id
, ads.name
, action_states.timestamp 
order by ad_media.ad_id;

我们也可以改写其他许多方法;但是要选择bset,我们需要了解更多关于您的架构的信息。数据。这篇文章提供了一些有用的相关信息:https://stackoverflow.com/a/7449213/361842(虽然专注于MSSQL而不是Postgres;但类似的想法适用)。