根据多个列值选择最具体的行匹配

时间:2017-07-03 05:25:42

标签: sql postgresql

我目前正致力于内容定位功能,我们根据其类别/国家/地区向医生展示不同的网页。

所以这是我们的医生表的样子,

 id |  name  | age | region | country | doctor_category 
----+--------+-----+--------+---------+-----------------
  1 | Deepak |  25 | APAC   | JP      | GP
  2 | Anil   |  25 | APAC   | JP      | null
  3 | Ajay   |  27 | APAC   | IN      | null
  4 | Amit   |  28 | NA     | CN      | null

我们所有的页面都是动态生成的,这是我们的页面表的样子,

 page_id | target_region | target_countries | target_categories 
---------+---------------+------------------+-------------------
       1 | APAC          | null             | null
       2 | APAC          | JP               | null
       3 | APAC          | JP               | GP
       4 | null          | null             | null

如果没有条件匹配,则页面4是默认页面

预期输出:(最佳特定匹配)

User(1) => Page(3)

User(2) => Page(2)

User(3) => Page(1)

User(4) => Page(4)

我在posgresql中使用CASE / GROUP BY/ DISTINCT ON尝试了很多,但没有成功,因为一个或多个场景失败了。我不是一个核心数据库人,所以我可能会缺少一些内置函数来实现相同的目标。

任何建议都将不胜感激。

2 个答案:

答案 0 :(得分:2)

另一种解决方案,仅适用于PostgreSQL:

SELECT DISTINCT
  id,
  first_value(page_id) OVER (
    PARTITION BY id
    ORDER BY target_categories IS NULL, target_countries IS NULL, target_region IS NULL
  )
FROM doctors
  LEFT JOIN pages ON (target_categories = doctor_category OR target_categories IS NULL)
    AND (target_countries = country OR target_countries IS NULL)
    AND (target_region = region OR target_region is null);

请注意,您的问题并未严格定义。好像一个页面与国家匹配但没有类别,而另一个页面与该类别匹配但没有国家,则不清楚哪个页面必须被选中。

通过选择哪个参数具有最高优先级来打破关系。这是ORDER BY行的工作。第一列具有最高优先级。随意改变它们发生的顺序。

否则查询的工作方式如下:

  • 选择医生可接受的所有页面
  • 为每位医生准确订购
  • 仅选择每位医生的第一个值
  • 由于查询会为每个可接受的页面生成一个(相同的)行,因此我们使用DISTINCT删除重复的行。

答案 1 :(得分:0)

试试这个

select d.*, (select Page_Id from PageTabl as p where d.Region = COALESCE(p.target_region,'NULL') 
    and COALESCE(d.Country,'NULL') = COALESCE(p.targer_countries,'NULL') 
    and COALESCE(d.Doctor_Category,'NULL') = COALESCE(p.targer_categories,'NULL')
    LIMIT 1) as Page_Id
from Doctors as d

或第二个wiche获得第一个匹配行

{{1}}

你可以改变合并取决于你的逻辑