在SELECT语句中对两列包含不同值的列进行分组

时间:2013-11-29 19:32:09

标签: sql sql-server group-by

我有一个SQL查询我正在对某些表SQL Server数据库执行。结果集看起来像这样:

Column1 | Column2 | Column3 | InvoiceNumber | InvoiceID
-------------------------------------------------------
1        1         1          1234            1
1        1         1          5678            2

我只想回到具有最小InvoiceID及其相应InvoiceNumber的行。

我在SELECT语句中应用min(InvoiceID)。在GROUP BY子句中,我按除InvoiceNumber和InvoiceID之外的每个列进行分组。我收到错误,因为InvoiceNumber不包含在SELECT语句中的聚合函数中,并且不存在于GROUP BY子句中。

如何构建查询,以便我只返回具有最小InvoiceID和相应InvoiceNumber的行?

修改

以下是一些其他信息:

结果集实际上将包含许多行。只是偶尔会有多行对Column1,Column2和Column3具有相同的值,但InvoiceNumber和InvoiceID的值不同。因此,结果集的更好示例如下所示:

Column1 | Column2 | Column3 | InvoiceNumber | InvoiceID
-------------------------------------------------------
1        1         1          1234            1
1        1         1          5678            2
2        1         1          1287            3
2        1         2          1287            3
2        2         1          1287            3
3        1         1          5555            4
3        1         2          5555            4

因此,当Column1,Column2和Column3相同时,我只想要具有最小InvoiceID的结果,以及具有最小InvoiceID的行的InvoiceNumber。在这种情况下,这就是我想要的实际情况:

Column1 | Column2 | Column3 | InvoiceNumber | InvoiceID
-------------------------------------------------------
1        1         1          1234            1
2        1         1          1287            3
2        1         2          1287            3
2        2         1          1287            3
3        1         1          5555            4
3        1         2          5555            4

只删除了第二行,因为它具有较小的InvoiceID,并且是唯一一个将Column1,Column2和Column3的值作为不同行的行。

这是我的SQL查询目前的样子:

SELECT c.CollectionID
    , p.Account
    , d.TransactionID
    , id.InvoiceNumber
    , i.InvoiceID
FROM collection c
INNER JOIN documents d on c.GlobalCollectionID = d.GlobalCollectionID
LEFT JOIN payment p on c.GlobalCollectionID = p.GlobalCollectionID
    AND d.TransactionID = p.TransactionID
LEFT JOIN invoice i on c.GlobalCollectionID = i.GlobalCollectionID
    AND d.TransactionID = i.TransactionID
LEFT JOIN invoicedata id on i.InvoiceID = id.InvoiceID
WHERE c.ProcessDate = '2013-11-29'
    AND c.Item = 11805123
    AND c.CollectionID in ('1104', '1105', '1106')
ORDER BY c.CollectionID
    , d.TransactionID
    , i.InvoiceID
    , p.Account

3 个答案:

答案 0 :(得分:1)

现在您提供了一些数据并且已经根据这些新数据和新要求更改了您的要求,请尝试此操作

DECLARE @T Table (Column1 INT,Column2 INT,Column3 INT,InvoiceNumber INT, InvoiceID INT)

INSERT INTO @T
VALUES
(1,1,1,1234,1),
(1,1,1,5678,2),
(2,1,1,1287,3),
(2,1,2,1287,3),
(2,2,1,1287,3),
(3,1,1,5555,4),
(3,1,2,5555,4)

;WITH CTE
 AS
   (
   SELECT Column1 ,Column2 
          ,Column3 ,InvoiceNumber , InvoiceID 
          , rn = ROW_NUMBER() OVER (PARTITION BY Column1 ,Column2 ,Column3  ORDER BY InvoiceID ASC)
   FROM @T
   )
 SELECT * FROM CTE
 WHERE rn = 1

结果集

Column1 Column2 Column3 InvoiceNumber   InvoiceID   rn
   1       1       1    1234               1        1
   2       1       1    1287               3        1
   2       1       2    1287               3        1
   2       2       1    1287               3        1
   3       1       1    5555               4        1
   3       1       2    5555               4        1

您的查询

;WITH CTE
 AS
   (
    SELECT YourQuery.* 
    , rn = ROW_NUMBER() OVER (PARTITION BY c.CollectionID , p.Account , d.TransactionID ORDER BY InvoiceID ASC)
    ( 
     SELECT c.CollectionID
        , p.Account
        , d.TransactionID
        , id.InvoiceNumber
        , i.InvoiceID
    FROM collection c
    INNER JOIN documents d on c.GlobalCollectionID = d.GlobalCollectionID
    LEFT JOIN payment p on c.GlobalCollectionID = p.GlobalCollectionID
        AND d.TransactionID = p.TransactionID
    LEFT JOIN invoice i on c.GlobalCollectionID = i.GlobalCollectionID
        AND d.TransactionID = i.TransactionID
    LEFT JOIN invoicedata id on i.InvoiceID = id.InvoiceID
    WHERE c.ProcessDate = '2013-11-29'
        AND c.Item = 11805123
        AND c.CollectionID in ('1104', '1105', '1106')
      )YourQuery
   )
 SELECT C.CollectionID , C.Account , C.TransactionID,C.InvoiceNumber, C.InvoiceID 
 FROM CTE C
 WHERE rn = 1

答案 1 :(得分:1)

如果您将SQL发布到初始查询中,可能会更容易提供帮助。

您可能希望将MIN()函数移动到WHERE子句中:

SELECT Column1 ,Column2 ,Column3 ,InvoiceNumber , InvoiceID
FROM Table_Name
WHERE InvoiceID = (SELECT MIN(InvoiceID) FROM Table_Name)

答案 2 :(得分:1)

这是您正在寻找的查询:

SELECT Column1, Column2, Column3, InvoiceNumber, InvoiceID
FROM ( 
    SELECT *,
        rn = ROW_NUMBER() OVER (PARTITION BY Column1, Column2, Column3
                                ORDER BY InvoiceID ASC)
    FROM example
) e
WHERE rn = 1

查看有关SQLFiddle 的信息。只需在查询中交换嵌套查询,但请保留ROW_NUMBER字段。

生成正确的结果集:

COLUMN1  COLUMN2  COLUMN3  INVOICENUMBER   INVOICEID
----------------------------------------------------
1        1        1        1234            1
2        1        1        1287            3
2        1        2        1287            3
2        2        1        1287            3
3        1        1        5555            4
3        1        2        5555            4