请求的SQL帮助:SELECT表A加入表B(最大或空)

时间:2011-04-19 21:06:25

标签: sql sql-server select left-join inner-join

在表A(别名ai)中,我有一个项目列表。在表B(别名aib)中,我有表A的所有项目的价格历史,但不是所有项目,对于那些,我需要SELECT NULL。我需要从表A中选择项目,它是表B中的最高价格或NULL。

这就是我所拥有的,但它不是很有用,如果表B有广泛的价格历史,我会得到重复的记录。

以下是不完全正常的查询:

SELECT *

FROM ItemGroup aig 

INNER JOIN Item ai ON ai.groupID = aig.ID 

LEFT JOIN Item_Prices aib ON ai.ID = aib.ItemID 

WHERE aig.ID = @groupID AND 
(aib.max_price = (SELECT MAX(price) AS highprice FROM Item_Prices 
  WHERE ItemID = ai.ID) 
  OR aib.price IS NULL) 

ORDER BY end_date

欢迎所有建议。

此致,

4 个答案:

答案 0 :(得分:1)

SELECT *
FROM ItemGroup aig
INNER JOIN Item ai ON ai.groupID = aig.ID
LEFT OUTER JOIN (
    SELECT 
        ItemID,MAX(max_price)
    FROM Item_Prices
    GROUP BY ItemID
) aib ON ai.ID=aib.ItemID
WHERE aig.ID = @groupID
ORDER BY end_date

子查询按ItemID获取最高价格,因此应过滤掉重复项。

答案 1 :(得分:1)

Ray,您是否只是使用item表将两个表连接在一起?如果您在查询的其余部分中不需要项目表中的任何其他内容,那么它就没有必要。

如果所有你真正想做的是“选择表A中的项目,它是表B中的最高价格或NULL。”如果Item_Prices.price允许null,那么就可以这么简单。

SELECT a.ItemName, MAX(b.price) AS 'MaxPrice' 
FROM Item AS a INNER JOIN Item_Prices AS b
ON a.groupID = b.ItemID
GROUP BY a.ItemName

以下是我的Item_Prices表格中的内容

Contents of Item_Prices listing several null and duplicate values

以下是我的项目表

中的内容

Contents of Item

查询结果:

Output from query

以下是我的Item表的设计视图,groupID是主键。

Design view of Item table with groupID as primary key

这是我的Item_Prices表的设计视图,您可以将ItemID设置为外键

Design view of Item_Prices with itemID as primary key

如果要从单独的表中选择数据,则不需要第三个表来为您或任何内容链接它们。只要表A中有某种类型的唯一标识符(主键)和表B中链接的匹配键(通常是外键),你就是金色的!

如果你打算将那个第三张桌子放到另一个场地,那么就不要理会了!我只是想举起一个简单的例子向你展示,因为当我在工作/学校时我看到很多人使用第三个表将表连接在一起,大部分时间都没有意义!

答案 2 :(得分:1)

@squillman几乎已经钉了它。优化

SELECT GroupID      = aig.groupID     ,
       ItemID       = ai.ID as ItemID ,
       HighestPrice = aib.HighestPrice
FROM      Item        ai
left join ( select ItemID ,
                   HighestPrice = max(price)
            from Item_Prices
            group by ItemID
          ) aib on aib.ItemID = ai.ID
WHERE ai.groupID = @groupID
ORDER BY end_date

如果您从表ItemGroup中查看的是组ID ...您不需要该表:您已经在Item表中获得了groupID,因此ItemGroup是不必要的,尽管您需要如果您需要ItemGroup中的其他属性,请保留它。保留ItemGroup不会对查询计划造成太大影响:您最多只需要一个组,并且可能ItemGroup在groupID上有覆盖索引。

子查询不需要

distinctgroup by ItemID使子查询结果集由ItemID唯一。这对性能有影响:distinct表示引擎必须确保结果集是唯一的。希望优化器会意识到group by使该集唯一并丢弃distinct,但我不会指望它。

答案 3 :(得分:0)

Select ...
From ItemGroup As AIG
    Join Item As AI
        On AI.ID = AIG.ID
Where AIG.Id = @groupId
    And Exists  (
                Select 1
                From Item_Prices As IP1
                    Join    (
                            Select IP2.ItemID, Max( IP2.Price ) As Price
                            From Item_Prices As IP2
                            Group By IP2.ItemId
                            ) As MaxPrices
                        On MaxPrices.ItemID = IP1.ItemID
                            And MaxPrices.Price = IP2.Price
                Where IP1.ItemID = AI.ID
                Union All
                Select 1
                From Item_Prices As IP1
                Where IP1.ItemID = AI.ID
                    And IP1.Price Is Null
                )
Order By End_Date