2009-08-18 18 views
0

我刚刚遇到了另一个SQL问题。我真的需要抽出一些时间来正确地学习。使用不同的外键从查询中选择行?

无论如何,我有这个查询,别人写道,它从几个不同的表中获取值。

现在多个项目可以具有相同的ProductID。因此,可能有3个项目返回所有具有相同ProductID但具有不同描述等等。

我想仅为每个ProductID选择1个项目。我尝试过使用DISTINCT和group,但是我收到了很多错误。这也适用于ACCESS数据库。

我认为这是因为选择查询中使用的逻辑搞乱了我的分组。

下面是该查询(我曾尝试将其格式化好一点,使用的在线工具,但它仍然是一个巨大的混乱)

SELECT tblproducts.productid, 
    tblproducts.categorycode, 
    tblproducts.scaletitle, 
    tblproducts.picture, 
    tblitems.cost, 
    tblitems.modelnumber, 
    tblitems.itemid, 
    Iif([tblitems]![tradeapproved],Iif(([tblitems]![markup]/100) <> 0,(Iif(([tblitems]![supplierdiscount]/100) <> 0, 
                       [tblitems]![cost] - ([tblitems]![cost] * ([tblitems]![supplierdiscount]/100)), 
                       [tblitems]![cost])) * ([tblitems]![markup]/100), 
             0) + Iif(([tblitems]![supplierdiscount]/100) <> 0, 
               [tblitems]![cost] - ([tblitems]![cost] * ([tblitems]![supplierdiscount]/100)), 
               [tblitems]![cost]) + [tblitems]![tradeapprovedcost] + [tblitems]![shippingcost], 
     Iif(([tblitems]![markup]/100) <> 0,(Iif(([tblitems]![supplierdiscount]/100) <> 0, 
                [tblitems]![cost] - ([tblitems]![cost] * ([tblitems]![supplierdiscount]/100)), 
                [tblitems]![cost])) * ([tblitems]![markup]/100), 
      0) + Iif(([tblitems]![supplierdiscount]/100) <> 0, 
         [tblitems]![cost] - ([tblitems]![cost] * ([tblitems]![supplierdiscount]/100)), 
         [tblitems]![cost]) + [tblitems]![shippingcost]) AS price 
FROM  (tblitems 
     INNER JOIN tblproducts 
     ON tblitems.productid = tblproducts.productid) 
    INNER JOIN tblsuppliers 
     ON tblproducts.supplierid = tblsuppliers.supplierid 
WHERE tblproducts.categorycode = 'BS' 
    AND tblitems.tradeapproved = 0 
    AND tblsuppliers.active = on 
    AND tblitems.isaccessory = false 
ORDER BY Iif([tblitems]![tradeapproved],Iif(([tblitems]![markup]/100) <> 0,(Iif(([tblitems]![supplierdiscount]/100) <> 0, 
                       [tblitems]![cost] - ([tblitems]![cost] * ([tblitems]![supplierdiscount]/100)), 
                       [tblitems]![cost])) * ([tblitems]![markup]/100), 
             0) + Iif(([tblitems]![supplierdiscount]/100) <> 0, 
               [tblitems]![cost] - ([tblitems]![cost] * ([tblitems]![supplierdiscount]/100)), 
               [tblitems]![cost]) + [tblitems]![tradeapprovedcost] + [tblitems]![shippingcost], 
     Iif(([tblitems]![markup]/100) <> 0,(Iif(([tblitems]![supplierdiscount]/100) <> 0, 
                [tblitems]![cost] - ([tblitems]![cost] * ([tblitems]![supplierdiscount]/100)), 
                [tblitems]![cost])) * ([tblitems]![markup]/100), 
      0) + Iif(([tblitems]![supplierdiscount]/100) <> 0, 
         [tblitems]![cost] - ([tblitems]![cost] * ([tblitems]![supplierdiscount]/100)), 
         [tblitems]![cost]) + [tblitems]![shippingcost]) 

任何人都可以发布此速战速决?由于

+2

该代码是一个血腥的迷宫。我尝试了格式化,但是到了晚上,我失去了耐心。你可以把它格式化成清晰的东西吗?或者可能发布简化版本? – Eric 2009-08-18 03:06:58

+0

@Eric,这里有同样的故事......试图格式化它,但放弃了。 – 2009-08-18 03:09:35

+0

好吧,我知道它很大,加上我已经给出的代码有12次这样的代码!这是一个噩梦,我会做出编辑并发布一个更好的 – ddd 2009-08-18 03:15:07

回答

1

好吧,既然你说你想了解这种东西:

内连接将连接项目以产品编号的,但会导致全套。所以,如果你有3个ProductIds和1项你会得到

ProdId ItemId Description 
1  1  Handy Dandy Randy Sandy! 
2  1  Easily Accessible personal grooming comb. 
3  1  This item provides a man or woman with extra re... 

那么你真正想要做的是让所有的ItemIds:

select ItemId from Item_tbl 

然后遍历每个结果,得到一个单一产品编号每个项目:

select top 1 ProductId from Product_tbl where ItemId = 12345 

现在任何人建议循环与SQL获取大喊,并(通常)正确如此。但是这是一个棘手的问题,因为这不是人们通常做的事情。

你是沿着正确的路线与群。 Group By说“合并所有具有不同列X的行”,其中列X将是ItemId。所以:给我一行ItemId

现在你必须不同于3种产品与产品编号项目Id 1 骗子办法做到这一点是不是选择一个产品编号为随机而是适合特定的聚合函数包含一个productId。最常见的是最小和最大。

select 
    ItemId, 
    max(ProductId) 
from Itemtbl i 
inner join Producttbl p 
    on i.itemid = p.itemId 
group by ItemId 

这将获得每个ItemId的最大ProductId。你也可以做同样的事情来获得最小的。

现在,最棘手的是找到符合标准的ProductId - 比如说最近更新的标准。你想说的是“选择ItemId和max(updatedDate),然后沿着拉取最大更新日期的ProductId - 但这在sql中不起作用(亲爱的上帝,我希望它做到了)。

这个查询将给不好的结果:

select 
    ItemId, 
    max(ProductId), 
    max(updatdedDate) 
from Itemtbl i 
inner join Producttbl p 
    on i.itemid = p.itemId 
group by ItemId 

因为最大的ProductId 不一定从最大updatedDate行来。

相反,你必须编写一个查询,这是否:

  1. 选择项目Id(例如5),以及maxUpdated日期(例如2005年5月5日)
  2. 返回到上Products_tbl和找到其ItemId为5且updatedDate为5/5/2005的ProductId

该查询留作练习。 (但有一个错误!如果有什么两款产品具有相同的最后更新日期和同一项目Id!

+0

我喜欢你的答案和努力。然而,它现在还没有真正帮助我。我知道SQL的基础知识,但是这个查询只是一个噩梦,无论我尝试什么,我都会得到很多错误,我认为这与if语句有关。 VS2008甚至无法解析查询!再次感谢 – ddd 2009-08-18 03:40:55

+0

我尝试将原始查询包装为派生表并选择特定属性。当我尝试在itemId上执行max时,我得到一个错误,显示产品ID没有聚合函数 – ddd 2009-08-18 03:52:46

+0

没有productId的聚合函数;你没有“group by”子句,所以你不能使用max。坦率地说,解决这个问题的最好方法是将其分解。检查你有什么桌子,你有什么PK和FK,然后弄清楚你想要得到什么。事实上,它看起来像意大利面条(甚至重新格式化)。 – 2009-08-18 04:32:36

1

第一步,以增加可读性为您创造tblItems一种观点认为,包括价格花哨的逻辑,如:

查看[vwItemsWithAdjustedCost]

SELECT 
    ProductID, 
    TradeApproved, 
    IsAccessory, 
    Cost, 
    ModelNumber, 
    ItemID, 
    IIf(
     (SupplierDiscount/100) <> 0, 
     Cost - (Cost * (SupplierDiscount/100)), 
     Cost 
    ) AS AdjustedCost 
FROM tblItems   

查看[vwItemsWithPrice]

SELECT 
    ProductID, 
    TradeApproved, 
    IsAccessory, 
    Cost, 
    ModelNumber, 
    ItemID, 
    IIf(
     (Markup/100) <> 0, 
     AdjustedCost * (Markup/100), 
     0 
    ) 
    + AdjustedCost 
    IIf(
     TradeApproved, 
     TradeApprovedCost, 
     0 
    ) 
    + ShippingCost AS Price 
FROM vwItemsWithAdjustedCost 

下一页如果3个项目具有相同的ID,您想要显示哪一个,您必须决定从多个匹配相同ProductID中选择一个项目的标准是什么?

正如汤姆说,一个简单的方法是只得到相匹配的第一个(最低)ID,这样的事情:

SELECT 
    P.ProductID, 
    P.CategoryCode, 
    P.ScaleTitle, 
    P.Picture, 
    IP.Cost, 
    IP.ModelNumber, 
    IP.ItemID, 
    IP.Price 
FROM 
    tblProducts P 
    INNER JOIN (
     SELECT 
      ProductID, 
      MIN(ItemID) AS MinItemID 
     FROM tblItems I 
     GROUP BY ProductID 
    ) S 
     ON S.ProductID = P.ProductID 
    INNER JOIN vwItemsWithPrice IP 
     ON IP.ItemID = S.MinItemID 
WHERE 
    P.CategoryCode = 'BS' 
    AND IP.TradeApproved = 0 
    AND IP.IsAccessory = false 
ORDER BY IP.Price 

这是说每个产品ID,给我的第一个(最低)的ItemID从tblItems,并使用该加入我的看法。

希望这会有所帮助!

+0

感谢您的回答,这是帮助。我试过你的方法,但我仍然有点卡住。我有你的最后一个片段,但没有按位置和顺序,只是选择*为简单。我在访问中出现语法错误,指向视图上的最终内连接。我甚至尝试用视图替换项目表,所以我知道不会有问题,但仍然是相同的错误。 – ddd 2009-08-18 10:21:07

+0

错误是语法错误操作失踪,显示代码为S ON S.ProductID = P.ProductID INNER JOIN(从tblItems选择项目ID)IP ON IP.ItemID = S.MinItemID – ddd 2009-08-18 10:24:07

+0

您使用Access和我认为它需要嵌套连接(从我使用它开始,可能是错误的),只需在第一个连接的周围放上括号,即FROM(tblProducts P ... ON S.ProductID = P.ProductID)INNER JOIN .. 。 – 2009-08-28 01:45:09

相关问题