如何对此查询进行分组以使其行为正确?

时间:2009-07-10 13:58:52

标签: sql sql-server tsql

我有一个名为Stock的表,另一个名为Listed,在Stock表中是一个状态代码,用于指示什么东西位于库存项目队列的前面 - 我希望能够找到最近添加的项目并将其设置为“队列前端”状态 例如,要列出所有列出的项目,然后按最近列出的项目进行排序 我会使用这个查询:

SELECT SKU FROM Stock
INNER JOIN Listed
ON Listed.ListingID = Stock.ListingID
WHERE Stock.StatusCode = 2
ORDER BY Listed.ListDate

但是我想找到我的Stock表中需要位于队列前面的所有项目 - 即。 StatusCode为1,其中这些项目没有状态码为1的SKU 例如我在Stock表中有几个具有各种ProductCodes的项目,但可以具有1和2的StatusCodes - 其中1表示队列中的第一个项目,2表示具有相同ProductCode的其余项目。

如何编写查询以设置所有需要StatusCode为1的项目,其中任何具有给定ProductCode的内容都没有,状态代码为1? 我想设置列出状态代码为1的最近添加的Stock项目,因为我必须将它们全部重置为2作为维护过程的一部分,并且需要恢复“队列前”项目。

最近添加的:ListDate
StatusCode:1(队列前面),2(其他有相同产品代码的商品)


以下是一些示例数据

股票表

SKU    ProductCode    StatusCode  
1      111111         1  
2      111111         2  
3      222222         1  
4      222222         2  
5      333333         2  
6      333333         2  

列出的表

ListID    SKU    ListDate
01        1      01/01/2009
02        2      02/01/2009
03        3      03/01/2009
04        4      04/01/2009
05        5      05/01/2009
06        6      06/01/2009

在库存表中,带有ProductCode 333333的SKU 6有两个具有相同StatusCode的项目,我想从列出的表中设置具有最新ListDate的项目 到StatusCode 1.这将适用于我最需要的所有其他情况 最近添加了具有此StatusCode的项目

3 个答案:

答案 0 :(得分:0)

这是pick-a-winner的变体......它是pick-all-losers

这是要点。有几个记录具有共同的价值,但一条记录是特殊的 - 它是胜利者。具有该共同价值的其余记录是输家。

例如,此查询使用最低ID从Customers中选择获胜者(每个名称)。它通过定义子查询中的获胜者来实现此目的。

SELECT *
FROM Customers c1
WHERE 
(
SELECT Min(CustomerID)
FROM Customers c2
WHERE c2.Name = c1.Name
GROUP BY c2.Name
) =  c1.CustomerID

然后选择输家是一个简单的改变:

SELECT *
FROM Customers c1
WHERE 
(
SELECT Min(CustomerID)
FROM Customers c2
WHERE c2.Name = c1.Name
GROUP BY c2.Name
) !=  c1.CustomerID

答案 1 :(得分:0)

UPDATE S1
SET S1.StatusCode = 1
FROM Stock S1
LEFT JOIN Stock S2
  ON (S1.ProductCode = S2.ProductCode
      AND S2.StatusCode = 1)
JOIN Listed L1
  ON (S1.SKU = L1.SKU)
WHERE S2.StatusCode IS NULL
 AND L1.ListDate =
 ( SELECT MIN(L2.ListDate)
     FROM Listed L2
    WHERE L1.SKU = L2.SKU )

有时候你说你想“找到”这样的项目(我猜这将是一个SELECT),有时你会说你想“设置”他们的状态代码 - 我采取后一种操作因为它似乎更好匹配你描述的问题,从而更新。

此外,当多个其他满意的项目具有相同的日期时,您不清楚您想要做什么,因此不可能唯一地定义最新的项目;也许在你的情况下其他的限制使这不可能吗?在这里,我设置了所有状态代码,当然也可以设置它们中的任何一个或者在某种程度上任意选择(通过按其他标准排序?)。

答案 2 :(得分:0)

这是共同主题的变体。与此类查询类似的应用程序用于处理重复行。在此senario中,您可能希望删除集合中除一行之外的所有行。

此查询解决了您的问题:

宣布@Stock AS TABLE(SKU Bigint,ProductCode Bigint,StatusCode Bigint)

插入@Stock VALUES(1,111111,1) 插入@Stock VALUES(2,111111,2) 插入@Stock VALUES(3,222222,1) 插入@Stock VALUES(4,222222,2) 插入@Stock VALUES(5,333333,2) 插入@Stock VALUES(6,333333,2)

DECLARE @Listed AS TABLE(ListID Bigint,SKU Bigint,ListDate DateTime)

插入@Listed VALUES(1,1,'01 / 01/2009')  插入@Listed VALUES(2,2,'02 / 01/2009')  插入@Listed VALUES(3,3,'03 / 01/2009')  插入@Listed VALUES(4,4,'04 / 01/2009')  插入@Listed VALUES(5,5,'05 / 01/2009')  插入@Listed VALUES(6,6,'06 / 01/2009')

更新@Stock SET StatusCode = 1 来自@Stock AS T1 INNER JOIN @Listed AS T2 ON T1.SKU = T2.SKU 哪里 T1.SKU IN

(从@Stock AS T3中选择TOP 1 T3.SKU             INNER JOIN @Listed AS T4 ON T3.SKU = T4.SKU             AND T3.ProductCode = T1.ProductCode ORDER BY ListDate)

AND ProductCode IN (SELECT DISTINCT ProductCode 来自@Stock AS S1 哪里不是(SELECT DISTINCT StatusCode FROM @Stock AS S2 WHERE S2.ProductCode = S1.ProductCode))