使用 SQL Server,如何将记录连接到所有“相似”记录的最小值同一个表中的记录?

发布于 2024-12-29 08:34:01 字数 7366 浏览 0 评论 0原文

[请原谅格式错误——首先在这里发帖,我认真地尝试做正确的事情]

从功能上来说,我只是想找到“类似”商品分组中价格最低的商品。例如——葡萄酒有很多,但我需要找到价格最低的750ml红葡萄酒和白葡萄酒;奶酪有很多,但我需要找到价格最低的 8 盎司 CHEDDAR 以及 FETA;等等。

我发现的所有解决方案都说要执行与我的代码中相同的操作。 我的“自加入”一定有问题。选择查询本身的运行时间不到 10 秒,嵌套选择也是如此。但是,当我尝试加入它们时,我的查询挂起并且永远不会完成。 必须有某种方法可以成功完成此加入。

我正在提取数百万行数据。每一行都是一个独特的商品/商店组合。我的嵌套选择试图找到非“名牌”商品的最低价格;最低价格是在“类似”商品中找到的,由以下列确定:store_name、category、subcategory、class、package_desc2、unit_name、chk(在我的查询中,“chk”由两个不同列的结果确定)。

这为我提供了上述列的所有组合的不同列表,以及每个组合的最低价格。我正在尝试将其加入到非“名称”品牌商品中,以查看我们在嵌套选择中找到的价格低廉的确切商品是什么。任何帮助表示赞赏!我已经研究了好几天了,但无法弄清楚。

这里的 SQL:

SELECT b.zone_name, 
       b.store_name, 
       b.family, 
       b.category, 
       b.subcategory, 
       b.class, 
       b.team, 
       b.subteam, 
       b.pos_dept, 
       b.brand_name, 
       b.item_description, 
       b.upc, 
       b.package_desc1         pkg, 
       b.package_desc2         sz, 
       b.unit_name, 
       CASE 
         WHEN b.good = 'good' 
               OR b.how_good = 1 THEN 'YES' 
         ELSE 'NO' 
       END                     AS chk, 
       b.eff_pricetype, 
       b.eff_price             low_price, 
       b.cd                    dollar_sales, 
       b.cu                    unit_sales, 
       b.cgm                   margin_dollars, 
       b.cgm / Nullif(b.cd, 0) AS margin_pct, 
       b.deleted_item, 
       b.discontinue_item, 
       b.not_available, 
       b.remove_item, 
       b.recall_flag, 
       CASE 
         WHEN 
SUM( 
Isnull(b.deleted_item, 0) + Isnull(b.discontinue_item, 0) + Isnull(b.not_available, 0) + Isnull(b.remove_item, 0) + Isnull(b.recall_flag, 0)) = 0 THEN
         'NO' 
  ELSE 'YES' 
END                     AS istatus, 
d.low 
FROM   mytable b 
       INNER JOIN(SELECT c.store_name, 
                         c.category, 
                         c.subcategory, 
                         c.class, 
                         c.package_desc2, 
                         c.unit_name, 
                         CASE 
                           WHEN c.good = 'good' 
                                 OR c.how_good = 1 THEN 'YES' 
                           ELSE 'NO' 
                         END              AS chk, 
                         MIN(c.eff_price) low 
                  FROM   mytable c 
                  WHERE  store_name = 'some store' 
                         AND brand_name NOT LIKE '%name%' 
                         AND weeks = 'Last 12 weeks' 
                         AND ( eff_pricetype = 'REG' 
                                OR eff_pricetype = 'EDV' 
                                OR eff_pricetype = 'GBC' 
                                OR eff_pricetype = 'CMP' 
                                OR eff_pricetype = 'LIN' 
                                OR eff_pricetype = 'FRZ' 
                                OR eff_pricetype = 'GBB' 
                                OR eff_pricetype = 'EDLP' 
                                OR eff_pricetype = 'GBN' 
                                OR eff_pricetype = 'GBR' 
                                OR eff_pricetype = 'MKT' 
                                OR eff_pricetype = 'COMP' 
                                OR eff_pricetype = 'R' 
                                OR eff_pricetype = 'COM' ) 
                         AND ( family = 'carrots' 
                                OR family = 'tomatoes' 
                                OR family = 'Cheese' 
                                OR family = 'Coffee' 
                                OR family = 'peppers' 
                                OR family = 'milk' 
                                OR family = 'oil' 
                                OR family = 'season' 
                                OR family = 'Housewares' 
                                OR family = 'paper' 
                                OR family = 'Meat' 
                                OR family = 'soup' 
                                OR family = 'nuts' 
                                OR family = 'pizza' 
                                OR family = 'potatoes' 
                                OR family = 'Seafood' 
                                OR family = 'beer' 
                                OR family = 'vitamins' 
                                OR family = 'Tea' 
                                OR family = 'Wine' 
                                OR family = 'beans' ) 
                  GROUP  BY c.store_name, 
                            c.category, 
                            c.subcategory, 
                            c.class, 
                            c.package_desc2, 
                            c.unit_name, 
                            c.good, 
                            c.how_good 
                  HAVING MIN(c.eff_price) > 0) AS d 
         ON b.store_name = d.store_name 
            AND b.category = d.category 
            AND b.subcategory = d.subcategory 
            AND b.class = d.class 
            AND b.package_desc2 = d.package_desc2 
            AND b.unit_name = d.unit_name 
            AND CASE 
                  WHEN b.good = 'good' 
                        OR b.how_good = 1 THEN 'YES' 
                  ELSE 'NO' 
                END = d.chk 
            AND b.eff_price = d.low 
WHERE  store_name = 'some store' 
       AND brand_name NOT LIKE '%name%' 
       AND weeks = 'Last 12 weeks' 
       AND ( eff_pricetype = 'REG' 
              OR eff_pricetype = 'EDV' 
              OR eff_pricetype = 'GBC' 
              OR eff_pricetype = 'CMP' 
              OR eff_pricetype = 'LIN' 
              OR eff_pricetype = 'FRZ' 
              OR eff_pricetype = 'GBB' 
              OR eff_pricetype = 'EDLP' 
              OR eff_pricetype = 'GBN' 
              OR eff_pricetype = 'GBR' 
              OR eff_pricetype = 'MKT' 
              OR eff_pricetype = 'COMP' 
              OR eff_pricetype = 'R' 
              OR eff_pricetype = 'COM' ) 
       AND ( family = 'carrots' 
              OR family = 'tomatoes' 
              OR family = 'Cheese' 
              OR family = 'Coffee' 
              OR family = 'peppers' 
              OR family = 'milk' 
              OR family = 'oil' 
              OR family = 'season' 
              OR family = 'Housewares' 
              OR family = 'paper' 
              OR family = 'Meat' 
              OR family = 'soup' 
              OR family = 'nuts' 
              OR family = 'pizza' 
              OR family = 'potatoes' 
              OR family = 'Seafood' 
              OR family = 'beer' 
              OR family = 'vitamins' 
              OR family = 'Tea' 
              OR family = 'Wine' 
              OR family = 'beans' ) 
GROUP  BY b.zone_name, 
          b.store_name, 
          b.family, 
          b.category, 
          b.subcategory, 
          b.class, 
          b.team, 
          b.subteam, 
          b.pos_dept, 
          b.brand_name, 
          b.item_description, 
          b.upc, 
          b.package_desc1, 
          b.package_desc2, 
          b.unit_name, 
          d.org, 
          b.eff_pricetype, 
          b.eff_price, 
          b.cd, 
          b.cu, 
          b.cgm, 
          b.deleted_item, 
          b.discontinue_item, 
          b.not_available, 
          b.remove_item, 
          b.recall_flag, 
          d.low, 
          b.good, 
          b.how_good 

[please forgive formatting errors-- first post here and I tried earnestly to do it right]

Functionally speaking, I'm simply trying to find the items that have the lowest price in its grouping of 'like' items. For example-- there are tons of wines, but I need to find the lowest priced 750ml RED as well as WHITE; there are tons of cheeses, but I need to find the lowest priced 8oz CHEDDAR as well as FETA; etc.

All solutions I've found say to do the same thing I have in my code. There must be a problem with my "self join". The select query on its own runs in less than 10 seconds, and so does the nested select. When I try to join them, though, my query hangs and never finishes. There must be some way to do this join successfully.

I have millions of rows of data I'm pulling from. Each row is a unique item/store combination. My nested select is trying to find the lowest price we have for items that are NOT "name" brand; the lowest price is found among 'like' items, as determined by the columns: store_name, category, subcategory, class, package_desc2, unit_name, chk (in my query, "chk" is determined by the result of two different columns).

This gives me the distinct list of all combinations of the aforementioned columns with the lowest price for each. I'm trying to join THAT to the non "name" brand items to see what the exact item(s) are that have that low price we found in the nested select. Any help is appreciated! I've been at this for days and can't figure it out.

SQL here:

SELECT b.zone_name, 
       b.store_name, 
       b.family, 
       b.category, 
       b.subcategory, 
       b.class, 
       b.team, 
       b.subteam, 
       b.pos_dept, 
       b.brand_name, 
       b.item_description, 
       b.upc, 
       b.package_desc1         pkg, 
       b.package_desc2         sz, 
       b.unit_name, 
       CASE 
         WHEN b.good = 'good' 
               OR b.how_good = 1 THEN 'YES' 
         ELSE 'NO' 
       END                     AS chk, 
       b.eff_pricetype, 
       b.eff_price             low_price, 
       b.cd                    dollar_sales, 
       b.cu                    unit_sales, 
       b.cgm                   margin_dollars, 
       b.cgm / Nullif(b.cd, 0) AS margin_pct, 
       b.deleted_item, 
       b.discontinue_item, 
       b.not_available, 
       b.remove_item, 
       b.recall_flag, 
       CASE 
         WHEN 
SUM( 
Isnull(b.deleted_item, 0) + Isnull(b.discontinue_item, 0) + Isnull(b.not_available, 0) + Isnull(b.remove_item, 0) + Isnull(b.recall_flag, 0)) = 0 THEN
         'NO' 
  ELSE 'YES' 
END                     AS istatus, 
d.low 
FROM   mytable b 
       INNER JOIN(SELECT c.store_name, 
                         c.category, 
                         c.subcategory, 
                         c.class, 
                         c.package_desc2, 
                         c.unit_name, 
                         CASE 
                           WHEN c.good = 'good' 
                                 OR c.how_good = 1 THEN 'YES' 
                           ELSE 'NO' 
                         END              AS chk, 
                         MIN(c.eff_price) low 
                  FROM   mytable c 
                  WHERE  store_name = 'some store' 
                         AND brand_name NOT LIKE '%name%' 
                         AND weeks = 'Last 12 weeks' 
                         AND ( eff_pricetype = 'REG' 
                                OR eff_pricetype = 'EDV' 
                                OR eff_pricetype = 'GBC' 
                                OR eff_pricetype = 'CMP' 
                                OR eff_pricetype = 'LIN' 
                                OR eff_pricetype = 'FRZ' 
                                OR eff_pricetype = 'GBB' 
                                OR eff_pricetype = 'EDLP' 
                                OR eff_pricetype = 'GBN' 
                                OR eff_pricetype = 'GBR' 
                                OR eff_pricetype = 'MKT' 
                                OR eff_pricetype = 'COMP' 
                                OR eff_pricetype = 'R' 
                                OR eff_pricetype = 'COM' ) 
                         AND ( family = 'carrots' 
                                OR family = 'tomatoes' 
                                OR family = 'Cheese' 
                                OR family = 'Coffee' 
                                OR family = 'peppers' 
                                OR family = 'milk' 
                                OR family = 'oil' 
                                OR family = 'season' 
                                OR family = 'Housewares' 
                                OR family = 'paper' 
                                OR family = 'Meat' 
                                OR family = 'soup' 
                                OR family = 'nuts' 
                                OR family = 'pizza' 
                                OR family = 'potatoes' 
                                OR family = 'Seafood' 
                                OR family = 'beer' 
                                OR family = 'vitamins' 
                                OR family = 'Tea' 
                                OR family = 'Wine' 
                                OR family = 'beans' ) 
                  GROUP  BY c.store_name, 
                            c.category, 
                            c.subcategory, 
                            c.class, 
                            c.package_desc2, 
                            c.unit_name, 
                            c.good, 
                            c.how_good 
                  HAVING MIN(c.eff_price) > 0) AS d 
         ON b.store_name = d.store_name 
            AND b.category = d.category 
            AND b.subcategory = d.subcategory 
            AND b.class = d.class 
            AND b.package_desc2 = d.package_desc2 
            AND b.unit_name = d.unit_name 
            AND CASE 
                  WHEN b.good = 'good' 
                        OR b.how_good = 1 THEN 'YES' 
                  ELSE 'NO' 
                END = d.chk 
            AND b.eff_price = d.low 
WHERE  store_name = 'some store' 
       AND brand_name NOT LIKE '%name%' 
       AND weeks = 'Last 12 weeks' 
       AND ( eff_pricetype = 'REG' 
              OR eff_pricetype = 'EDV' 
              OR eff_pricetype = 'GBC' 
              OR eff_pricetype = 'CMP' 
              OR eff_pricetype = 'LIN' 
              OR eff_pricetype = 'FRZ' 
              OR eff_pricetype = 'GBB' 
              OR eff_pricetype = 'EDLP' 
              OR eff_pricetype = 'GBN' 
              OR eff_pricetype = 'GBR' 
              OR eff_pricetype = 'MKT' 
              OR eff_pricetype = 'COMP' 
              OR eff_pricetype = 'R' 
              OR eff_pricetype = 'COM' ) 
       AND ( family = 'carrots' 
              OR family = 'tomatoes' 
              OR family = 'Cheese' 
              OR family = 'Coffee' 
              OR family = 'peppers' 
              OR family = 'milk' 
              OR family = 'oil' 
              OR family = 'season' 
              OR family = 'Housewares' 
              OR family = 'paper' 
              OR family = 'Meat' 
              OR family = 'soup' 
              OR family = 'nuts' 
              OR family = 'pizza' 
              OR family = 'potatoes' 
              OR family = 'Seafood' 
              OR family = 'beer' 
              OR family = 'vitamins' 
              OR family = 'Tea' 
              OR family = 'Wine' 
              OR family = 'beans' ) 
GROUP  BY b.zone_name, 
          b.store_name, 
          b.family, 
          b.category, 
          b.subcategory, 
          b.class, 
          b.team, 
          b.subteam, 
          b.pos_dept, 
          b.brand_name, 
          b.item_description, 
          b.upc, 
          b.package_desc1, 
          b.package_desc2, 
          b.unit_name, 
          d.org, 
          b.eff_pricetype, 
          b.eff_price, 
          b.cd, 
          b.cu, 
          b.cgm, 
          b.deleted_item, 
          b.discontinue_item, 
          b.not_available, 
          b.remove_item, 
          b.recall_flag, 
          d.low, 
          b.good, 
          b.how_good 

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

命硬 2025-01-05 08:34:01

您可以通过将系列和价格类型子句更改为使用 IN 而不是 OR 来简化代码并可能提高性能。

例如:

   AND eff_pricetype IN ('REG','EDV','GBC','CMP','LIN','FRZ',
                         'GBB','EDLP','GBN','GBR','MKT','COMP','R','COM') 

   AND family IN ('carrots','tomatoes','Cheese','Coffee', etc...

另外,如果您的子查询按照您所说的那样工作,您可以将它们放入两个不同的表变量中,然后连接它们。

You can simplify your code and possibly improve performance by changing your family and pricetype clauses to use IN instead of OR.

For example:

   AND eff_pricetype IN ('REG','EDV','GBC','CMP','LIN','FRZ',
                         'GBB','EDLP','GBN','GBR','MKT','COMP','R','COM') 

   AND family IN ('carrots','tomatoes','Cheese','Coffee', etc...

Also, if your subqueries are working as you say they are, you could put them into two different table variables and then join them.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文