在 PostgreSQL 中按特定列数据选择行

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

我正在尝试构建一个菜谱查找应用程序(PERN stack),就像SuperCook,但我的 postgres 表遇到了一些问题。

所需结果的简短描述。我希望用户选择一些成分并返回只能使用这些成分制作的食谱。

我使用 pgadmin 从 Recipe Dataset 导入表并设置我的 Nodejs 服务器和路由。

我的问题是我不知道如何返回仅包含所选成分的食谱。

据我所知,WHERE、LIKE 和逻辑运算符无法帮助我(但我是初学者,所以我知道的不多),因为使用它们将返回包含所选成分 + 任何其他成分的食谱。

对于此类问题,我们唯一关心的列是 NER 列,因为它仅包含成分。我看到它们写得像一个javascript对象,例如:

"[""sesame seed"", ""soy sauce"", ""honey"", ""vegetable cooking spray"", ""thin green onion strips"", ""grated ginger"", ""chicken""]"

在 pgAdmin 中出现如下:

["sesame seed", "soy sauce", "honey", "vegetable cooking spray", "thin green onion strips", "grated ginger", "chicken"]

问题:如何从我的表格中仅选择包含完全所选成分或至少组合其中无特定顺序的食谱?

例如:

输入:鸡肉,黄油,洋葱,大蒜

输出NER配方:

["butter", "chicken", "garlic", "onion"]

或带有NER的食谱:

["butter", "chicken"]

或带有NER的食谱:

["garlic", "chicken"]

sql node.js database postgresql
1个回答
0
投票

一种选择是使用 json 函数将您的配料(用户的和菜肴的)排列成行。通过这种方式,您可以加入每种成分的数据,您可以计算出您拥有的成分数量与所需成分总数的比较,并获得其百分比。您还可以提供缺少成分的清单。

WITH    --  S a m p l e    D a t a :   
  ingredients ( id, dish, ner ) As
    ( Select 1, 'Jewell Ball''S Chicken', '["cream of mushroom soup", "beef", "sour cream", "chicken breasts"]' Union All
      Select 2, 'Creamy Corn', '["frozen corn", "pepper", "cream cheese", "garlic powder", "butter", "salt"]' Union All
      Select 3, 'Chicken Funny', '["chicken gravy", "cream of mushroom soup", "chicken", "shredded cheese"]' Union All
      Select 4, 'Nolan''S Pepper Steak', '["oil", "tomatoes", "green peppers", "water", "onions", "worcestershire sauce"]' Union All
      Select 5, 'Yor sample dish', '["butter", "chicken", "garlic", "onion"]'
    ),

...使用 json,将菜肴成分转置为行...

  dish_ingredients As
    ( Select  i.id, i.dish, Replace(json_array_elements(i.ner::json)::text, '"', '') as dish_ingredient 
      From    ingredients i
    ),

...不知道您将如何提供用户成分数据,所以我将您的成分问题列表放入 cte 中,并执行与上面相同的操作以将它们排成行....

  user_input As
    ( Select Replace(json_array_elements( array_to_json(string_to_array('chicken, butter, onion, garlic', ', ')) )::text, '"', '') as user_ingredient 
    ), 

...创建另一个 cte 来组合菜肴和用户成分,为使用它们的不同选项准备数据(有或没有成分、所需的总成分、百分比...)

  • 答案末尾的网格cte结果集
  grid As 
    ( Select    d.id, d.dish, dish_ingredient, ui.user_ingredient, 
                Case When  ui.user_ingredient Is Null Then 1 End as flag_have_not, 
                Case When  ui.user_ingredient Is Not Null Then 1 End as flag_have, 
                -- 
                Count(Case When ui.user_ingredient Is Not Null Then d.id End)
                      Over(Partition By d.id) as cnt_have,
                Count(d.id) Over(Partition By d.id) as cnt_dish_ingredient, 
                --
                Round(Count(Case When ui.user_ingredient Is Not Null Then d.id End)
                            Over(Partition By d.id)::Decimal 
                      * 100 / Count(d.id) Over(Partition By d.id)
                    , 2) as pct_match
      From      dish_ingredients d
      Left Join user_input ui ON( Position(ui.user_ingredient In d.dish_ingredient) > 0 )
    ) 

...这是主要的sql - 获取用户拥有50%或更多食材的菜肴...

--    M a i n    S Q L :
Select    id, dish, Max(pct_match) as pct_match,
          string_agg(Case When flag_have_not = 1 Then dish_ingredient End, ',  ' Order By user_ingredient) as missing_ingredients
From      grid
Where     pct_match >= 50
Group  By id, dish 
/*    R e s u l t :
id  dish                pct_match   missing_ingredients
--  ------------------  ---------   ----------------------------------------------------
 3  Chicken Funny           50.00   cream of mushroom soup,  shredded cheese
 5  Yor sample dish        100.00   null                                                   */

注意
您应该注意多词成分和可能的错过匹配或错误匹配以及其他问题(可能使用 Like 进行匹配)。下面是网格 cte 结果集:

/*    R e s u l t :     ( grid )
id  dish                       dish_ingredient           user_ingredient    flag_have_not   flag_have   cnt_have  cnt_dish_ingredient   pct_match
--  -------------------------  ------------------------  -----------------  -------------   ---------   --------  -------------------   ---------
1   Jewell Ball'S Chicken      cream of mushroom soup    null                           1        null          1                    4       25.00
1   Jewell Ball'S Chicken      beef                      null                           1        null          1                    4       25.00
1   Jewell Ball'S Chicken      sour cream                null                           1        null          1                    4       25.00
1   Jewell Ball'S Chicken      chicken breasts           chicken                     null           1          1                    4       25.00
2   Creamy Corn                frozen corn               null                           1        null          2                    6       33.33
2   Creamy Corn                pepper                    null                           1        null          2                    6       33.33
2   Creamy Corn                cream cheese              null                           1        null          2                    6       33.33
2   Creamy Corn                garlic powder             garlic                      null           1          2                    6       33.33
2   Creamy Corn                butter                    butter                      null           1          2                    6       33.33
2   Creamy Corn                salt                      null                           1        null          2                    6       33.33
3   Chicken Funny              chicken gravy             chicken                     null           1          2                    4       50.00
3   Chicken Funny              cream of mushroom soup    null                           1        null          2                    4       50.00
3   Chicken Funny              chicken                   chicken                     null           1          2                    4       50.00
3   Chicken Funny              shredded cheese           null                           1        null          2                    4       50.00
4   Nolan'S Pepper Steak       oil                       null                           1        null          1                    6       16.67
4   Nolan'S Pepper Steak       tomatoes                  null                           1        null          1                    6       16.67
4   Nolan'S Pepper Steak       green peppers             null                           1        null          1                    6       16.67
4   Nolan'S Pepper Steak       water                     null                           1        null          1                    6       16.67
4   Nolan'S Pepper Steak       onions                    onion                       null           1          1                    6       16.67
4   Nolan'S Pepper Steak       worcestershire sauce      null                           1        null          1                    6       16.67
5   Yor sample dish            butter                    butter                      null           1          4                    4      100.00
5   Yor sample dish            chicken                   chicken                     null           1          4                    4      100.00
5   Yor sample dish            garlic                    garlic                      null           1          4                    4      100.00
5   Yor sample dish            onion                     onion                       null           1          4                    4      100.00      */
© www.soinside.com 2019 - 2024. All rights reserved.