面试问题的最佳解决方案

时间:2011-04-11 17:02:16

标签: sql

最近在求职面试中,我遇到了以下问题。

说我有下表

widget_Name        |     widget_Costs      | In_Stock
---------------------------------------------------------
a                   |         15.00          |    1
b                   |         30.00          |    1
c                   |         20.00          |    1
d                   |         25.00          |    1

其中widget_name包含窗口小部件的名称,widget_costs是窗口小部件的价格,库存中的常量为1.

现在我的商业保险有一定的免赔额。我期待找到一个sql语句,告诉我每个小部件,它的价格超过免赔额。因此,如果我的可扣除价格是50.00美元,则上面只会返回

widget_Name        |     widget_Costs      | In_Stock
---------------------------------------------------------
a                   |         15.00          |    1
d                   |         25.00          |    1

由于小部件b和c用于满足免赔额

我能得到的最接近的是

SELECT 
    *
FROM (
     SELECT 
          widget_name, 
          widget_price
     FROM interview.tbl_widgets
     minus
     SELECT widget_name,widget_price
     FROM (
          SELECT 
               widget_name,
               widget_price, 
               50 - sum(widget_price) over (ORDER BY widget_price  ROWS between unbounded preceding and current row) as running_total
          FROM interview.tbl_widgets 
     ) 
     where  running_total >= 0
)
;

哪个给了我

widget_Name        |     widget_Costs      | In_Stock
---------------------------------------------------------
c                   |         20.00          |    1
d                   |         25.00          |    1

因为它使用a和b来满足大部分免赔额

我希望有人能够向我展示正确的答案

编辑:我理解面试问题要问这个问题。给出一个小部件及其价格表并给出一个美元金额,减去尽可能多的小部件,你可以达到美元金额并返回那些小部件及其价格仍然存在

3 个答案:

答案 0 :(得分:2)

我会给出一个答案,以防万一它比它看起来容易,但如果想法只是为了返回任何费用超过免赔额的小部件那么你会做这样的事情:

Select
  Widget_Name, Widget_Cost, In_Stock
From
  Widgets
Where
  Widget_Cost > 50 -- SubSelect for variable deductibles?

对于您的示例数据,我的查询不返回任何行。

答案 1 :(得分:2)

我相信我理解你的问题,但我不是100%。这就是我所说的你的意思:

你的免赔额是50美元。为了满足免赔额,你可以“使用”两件物品。 (它总是两个吗?它能走多远?它可以只是一个吗?如果它们不完全合计50美元,那么会有很多缺失的信息)。然后,您想要返回用于免赔额的小部件。我有以下内容。

CREATE TABLE #test
(
    widget_name char(1),
    widget_cost money
    )

INSERT INTO #test (widget_name, widget_cost)
SELECT 'a', 15.00 UNION ALL
SELECT 'b', 30.00 UNION ALL
SELECT 'c', 20.00 UNION ALL
SELECT 'd', 25.00 


SELECT * FROM #test t1 
WHERE t1.widget_name NOT IN (
SELECT t1.widget_name FROM #test t1
CROSS JOIN #test t2
WHERE t1.widget_cost + t2.widget_cost = 50 AND t1.widget_name != t2.widget_name)

返回

widget_name widget_cost
----------- ---------------------
a           15.00
d           25.00

答案 2 :(得分:1)

这看起来像Bin Packing problem,这些很难解决,特别是使用SQL。

如果你搜索Bin Packing + SQL的SO,你会发现how to find Sum(field) in condition ie “select * from table where sum(field) < 150”除了你想要添加一个NOT IN之外,这基本上是同一个问题。

我无法通过brianegge得到公认的答案,但他一般写的内容很有意思

  

..问题你   描述想要选择   最贴切的用户   到一个给定的大小,是一个bin包装   问题。这是NP-Hard问题,   并且不容易用ANSI解决   SQL。但是,以上似乎   返回正确的结果,但事实上   它只是从最小的开始   项目,并继续添加项目,直到   垃圾箱已满。

     

一般的,更有效的垃圾箱包装   算法就是从   最大的项目并继续添加   较小的适合。这个   算法将选择用户5和4。

所以有了这个建议,你可以编写一个游标来遍历表格来做这件事(它不会很漂亮)。

Aaron Alton提供了一个很好的链接series of articles试图用sql解决Bin Packing问题,但基本上得出的结论是它最好用光标来做。