【问题标题】:SQL query to get a bin with the smallest amount of an itemSQL 查询以获取项目数量最少的 bin
【发布时间】:2016-06-01 15:08:12
【问题描述】:

我有一个如下所示的表格:

|Bin    |Item       |Amnt
|-------|-----------|----
|01SIS  |BA0001-BLK |7
|01A1   |BA0001-BLK |1
|01SIS  |BA0001-KAK |1
|01A1   |BA0001-KAK |5

我想得到每个 Item 数量最少的 Bin,如下所示:

|Bin    |Item       |Amnt
|-------|-----------|----
|01A1   |BA0001-BLK |1
|01SIS  |BA0001-KAK |1

看起来很简单,但分组很棘手。 有人有什么建议吗?

【问题讨论】:

  • 这看起来一点也不棘手。这似乎非常简单。你试过什么?

标签: sql sql-server tsql group-by min


【解决方案1】:

作为第一步,您希望获得每个项目的最低编号。

SELECT Item, MIN(Amnt) AS Amnt
INTO #MinCounts
FROM Table
GROUP BY Item

知道了这一点,然后您将该数据集内部连接到原始表,以消除任何与您的最小计数不匹配的项目。

SELECT *
FROM Table T
INNER JOIN #MinCounts MC
ON MC.Item = MC.Item
AND MC.Amnt = T.Amnt

如果“最小”数字匹配多个项目,这将为您提供重复项。

【讨论】:

  • 您不能使用 MIN(*)。它必须是一列,在这种情况下,我猜是 Amnt。我不知道我会为此使用临时表,但这是一种方法。
  • 我的速度有点太快了,我已经做出了改变。此外,您可以随意使用 CTE、子查询或表变量。
【解决方案2】:

试试这样的:

SELECT * 
FROM YourTable AS tbl
WHERE tbl.Amnt = (SELECT MIN(Amnt) FROM YourTable Where YourTable.Item = tbl.Item);

【讨论】:

    【解决方案3】:

    返回多条记录的高效版本

    我将假设您至少使用 SQL Server 2008 及更高版本。 我相信我的版本应该非常有效,具体取决于您返回大量数据的索引。这可以通过 Amnt 对每个 Bin 进行排名,然后选择最低的 Amnt

    SELECT *
    FROM
    (
        SELECT *,AmntRank = ROW_NUMBER() OVER (PARTITION BY Bin ORDER BY Amnt) 
        FROM YourTable
    ) AS A
    WHERE AmntRank = 1 /*Only select lowest Amount for each Bin*/
    

    【讨论】:

      【解决方案4】:

      您可以使用 CROSS APPLY 获取每个 bin 的最小值,并结合 DISTINCT 删除重复项:

      SELECT DISTINCT
             Bin ,
             details.Item ,
             details.Amt
      FROM dbo.Data do
      CROSS APPLY ( SELECT TOP 1
                               Amt,
                               Item
                        FROM    dbo.Data di
                        WHERE   di.Bin = do.Bin
                        ORDER BY  AMT DESC
                  ) details
      

      【讨论】:

        【解决方案5】:

        这个 Group by 应该可以工作

        SELECT DISTINCT
               Bin ,
               Item ,
               Amt
        FROM YourTable do
        INNER JOIN (SELECT Bin. MIN(Amnt)Amt FROM YourTable GROUP BY Bin) Tmp
        On Tmp.Bin = do.Bin and details.Amt = Tmp.Amt
        

        【讨论】:

          【解决方案6】:
          ;with mytable as
          (
            select '01SIS' as Bin, 'BA0001-BLK' as Item, 7 as Amnt
            union all
            select '01A1'   , 'BA0001-BLK', 1
            union all
            select '01SIS'  , 'BA0001-KAK', 1
            union all
            select '01A1'   , 'BA0001-KAK', 5
          )
          select top 1 with ties *
          from mytable
          order by Amnt asc
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2012-11-26
            • 2013-01-18
            • 1970-01-01
            • 1970-01-01
            • 2017-07-08
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多