【问题标题】:SQL Query to Find Most Effective Data查找最有效数据的 SQL 查询
【发布时间】:2013-02-14 07:58:06
【问题描述】:

我想编写查询以查找最有效的行。我有这些表:

Sellers
Id   Name
1    Mark
2    Julia
3    Peter

Stocks
 Id   SellerId   ProductCode   StockCount
 1       1         30A            10
 2       2         20A             4
 3       1         20A             2
 4       3         42B             3

还有 sqlfiddle http://sqlfiddle.com/#!6/fe5b1/1/0

我的意图是为库存找到最佳卖家。

如果客户需要 30A、20A 和 42B 产品。我需要返回“Mark”和“Peter”,因为 Mark 有两种产品(30A 和 20A),所以不需要 Julia。

如何在 sql 中解决这个问题?

【问题讨论】:

  • 您使用的是哪种 RDBMS,MS SQL Server、MySQL、PostgreSQL...?我猜 MS SQL Server 作为 SQL Fiddle 正在使用它。添加所需的标签。以及您添加的 SQL Fiddle 链接,最好编辑您的问题并将其添加到那里,因此查看问题的其他用户不需要通过所有 cmets 来确保他们拥有所有信息
  • 我认为这里的问题是 Ozan 想要找到可以完成订单的最少供应商数量。您可能希望按供应商可以提供的物品总数对供应商列表进行排序,但编码可能很棘手。
  • 我认为你的问题比这里描述的更复杂。如果两个卖家的产品数量相同(但产品不同?)
  • 为什么不需要 Julia?彼得也没有 30A。你应该只返回 Mark,因为他已经卖出了 14 只股票,然后是 Julia 4 和 Peter 3……我不明白你想在这里实现什么。
  • @GilPeretz 如果我需要返回它们两个。另一种情况,如果 mark 有 42B,那么 peter 会禁用。

标签: sql tsql sql-server-2012


【解决方案1】:

在临时表的帮助下让它工作

SELECT
  s.SellerId,
  ProductList = STUFF((
                       SELECT ',' + ProductCode FROM Stocks
                        WHERE s.SellerId = Stocks.SellerId
                        ORDER BY ProductCode FOR XML PATH('')
                       )
                      , 1, 1, ''), COUNT(*) AS numberOfProducts
INTO #tmptable
FROM
  Stocks s
WHERE
  s.ProductCode IN ('30A','20A','42B')
  AND s.StockData > 0
GROUP BY s.SellerId;

/*this second temp table is necessary, so we can delete from one of them*/
SELECT * INTO #tmptable2 FROM #tmptable; 

DELETE t1 FROM #tmptable t1
WHERE EXISTS (SELECT 1 FROM #tmptable2 t2
               WHERE t1.SellerId != t2.SellerId
                 AND t2.ProductList LIKE '%' + t1.ProductList + '%'
                 AND t2.numberOfProducts > t1.numberOfProducts)
;

SELECT Name FROM #tmptable t INNER JOIN Sellers ON t.SellerId = Sellers.Id;

更新:

请尝试使用静态表:

CREATE TABLE tmptable (SellerId int, ProductList nvarchar(max), numberOfProducts int);

对于 tmpTable2 也是如此。然后把上面的代码改成

INSERT INTO tmpTable
SELECT
  s.SellerId,
  ProductList = STUFF((
                       SELECT ',' + ProductCode FROM Stocks
                        WHERE s.SellerId = Stocks.SellerId
                        ORDER BY ProductCode FOR XML PATH('')
                       )
                      , 1, 1, ''), COUNT(*) AS numberOfProducts
FROM
  Stocks s
WHERE
  s.ProductCode IN ('30A','20A','42B')
  AND s.StockData > 0
GROUP BY s.SellerId;

INSERT INTO tmpTable2 SELECT * FROM tmpTable;

DELETE t1 FROM tmptable t1
WHERE EXISTS (SELECT 1 FROM tmptable2 t2
               WHERE t1.SellerId != t2.SellerId
                 AND t2.ProductList LIKE '%' + t1.ProductList + '%'
                 AND t2.numberOfProducts > t1.numberOfProducts)
;

SELECT * FROM tmpTable;
DROP TABLE tmpTable, tmpTable2;

【讨论】:

  • 一个问题,例如查询在真实数据中不起作用。它返回所有产品,因此查询不能从真实数据中的 temptable 中删除,我们的 productList 值有时太长,例如 1000 个字符长度,所以您认为这是合理还是不合理?
  • 我无法理解这个问题。您是否收到错误提示,例如临时表太大而不能成为临时表?如果是,请删除临时表名称前的#,并在不再需要时删除这些表。
  • 您的代码在 sqlfiddle 上运行良好。当我在真实数据库中运行您的查询时,它不会按我的意愿工作。因此,我查看您的查询,我意识到“AND t2.ProductList LIKE '%' + t1.ProductList + '%'”代码无法找到并且存在查询无法从#tmptable 中删除,因此所有使用 numberOfProducts 列列出的产品。 ProductList 字符串长度在某些行中为 1000 个字符。也许这就是问题所在?
  • @OzanWt 更新了我的答案。
  • 谢谢,但我试过它没有解决问题。我的最后一条评论是我试图解释问题。 like 子句有什么限制吗?
【解决方案2】:

我想这可能就是您要找的东西?

Select name,sum(stockdata) as stockdata from sellers s1 join Stocks s2 on s1.id=s2.sellerid
where ProductCode in ('30A','20A','42B')
group by name
order by sum(stockdata) desc

希望对你有帮助。

如果您只想要前 2 名。你写

Select top 2 name,sum(stockdata) as stockdata from sellers s1 join Stocks s2 on s1.id=s2.sellerid
where ProductCode in ('30A','20A','42B')
group by name
order by sum(stockdata) desc

我想这就是你要找的东西,既然我这么看,你要选择stockdata最高的两个人?

【讨论】:

  • 不,这不是他要找的东西。他只是不想要 Julia,因为 Mark 拥有她的产品加上另一个产品,因此 Mark 更“有效”。
  • 啊,嘿嘿抱歉:)
猜你喜欢
  • 2022-01-25
  • 1970-01-01
  • 2016-04-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-31
  • 1970-01-01
相关资源
最近更新 更多