【问题标题】:SQL Help Requested: SELECT Table A Joined with Table B (Max or Null)请求 SQL 帮助:SELECT 表 A 与表 B 连接(最大或空)
【发布时间】:2011-04-19 21:06:25
【问题描述】:

在表 A(别名 ai)中,我有一个项目列表。在表 B(别名 aib)中,我有表 A 的所有项目的价格历史记录,但不是所有项目,对于那些,我需要选择 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

欢迎所有建议。

尊敬的,

【问题讨论】:

  • 这里也有C表吗?
  • 抱歉遗漏了重要的事实:SQL Server 2008 R2 和是的,有一个表 C。

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


【解决方案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 上有一个覆盖索引。

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

【讨论】:

  • 对 SQL Server 2008 R2 稍作调整即可完美运行。感谢大家的大力支持!
【解决方案2】:

Ray,您只是使用 item 表将两个表连接在一起吗?如果您在查询的其余部分不需要 item 表中的任何其他内容,则实际上没有必要。

如果all你真正想做的是“从表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 表中的内容

这是我的项目表中的内容

查询结果:

这里是我的Item表的设计视图,groupID为主键。

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

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

如果您确实打算将第三张桌子放在另一个领域,那么请忽略!我只是想举一个简单的例子来向您展示,因为当我在工作/学校时,我看到很多人使用第三个表将表链接在一起,这在大多数情况下是没有意义的!

【讨论】:

  • 感谢您加倍努力。对不起,是的,有一张桌子 C。
  • 没问题,我想为任何有上述不良习惯的人提供它:P
  • You JOIN by groupID 这是一个键,但你 GROUP BY ItemName 这不是一个键并且可以为空:这真的是你想要的,即用不同的“主要标识符”分组项目但名称相同(可能为 NULL)?在我看来,你会得到更可靠的结果 GROUP BY groupID 即关键。
  • 不...您必须根据 SQL 语法按 ItemName 分组。 (MAX函数)
【解决方案3】:
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 获取您的最高价格,因此应该过滤掉重复项。

【讨论】:

  • 子查询中不需要distinctGroup by ItemID 使子查询结果按 itemID 区分。
  • @Niholas True dat... 拿出来。
【解决方案4】:
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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-16
    • 2012-09-18
    • 1970-01-01
    • 1970-01-01
    • 2020-07-20
    • 2015-09-19
    相关资源
    最近更新 更多