假设我有下面的SQL查询(Notice the JOIN
):
SELECT
bpq.Id,
b.BatchCode,
bpq.PartId,
bpq.Hkid
FROM
BoxPartsQuantity bpq
JOIN
Batch b
ON
bpq.BatchId = b.Id
WHERE
PartId = 1
并且返回的结果是:
Id BatchCode PartId Hkid
137 2016-03-31 1 34361
138 2016-03-31 1 34361
139 2016-03-31 1 34361
140 2016-03-31 1 34361
141 2016-03-31 1 34361
1123 2016/04/19 1 34361
1976 2016/04/29 1 34361
我如何删除BatchCode
和Hkid
中的重复项,假设我想要如下结果:
Id BatchCode PartId Hkid
137 2016-03-31 1 34361
1123 2016/04/19 1 34361
我已尝试过以下代码:
SELECT
bpq.Id,
b.BatchCode,
bpq.PartId,
bpq.Hkid
FROM
BoxPartsQuantity bpq
JOIN
Batch b
ON
bpq.BatchId = b.Id
WHERE
PartId = 1
GROUP BY
b.BatchCode,
bpq.Hkid
但是它返回了我的错误:
[SQL]SELECT bpq.Id, b.BatchCode, bpq.PartId, bpq.Hkid FROM BoxPartsQuantity bpq JOIN Batch b ON bpq.BatchId = b.Id WHERE PartId = 1 GROUP BY b.BatchCode, bpq.Hkid
[Err] 42000 - [SQL Server] Column' BoxPartsQuantity.Id'在选择列表中无效,因为它不包含在聚合中 函数或GROUP BY子句。
我对我应该做什么和必须做什么非常困惑,因为我对SQL编码及其所有知识都不是很了解。谢谢
答案 0 :(得分:2)
您必须对未参与GROUP BY
子句的记录使用聚合函数:
SELECT
MIN(bpq.Id),
b.BatchCode,
bpq.PartId,
bpq.Hkid
FROM
BoxPartsQuantity bpq
JOIN
Batch b
ON
bpq.BatchId = b.Id
WHERE
PartId = 1
GROUP BY
b.BatchCode,
bpq.Hkid,
bpq.PartId
上述查询还在bpq.PartId
中放置了字段GROUP BY
。这对分组没有任何影响,因为PartId=1
返回了所有记录。对MIN
字段使用bpq.Id
,查询会返回每b.BatchCode, bpq.Hkid
组记录的最小值,与OP中引用的预期结果一样。
答案 1 :(得分:2)
错误正在发生,因为bpq.id
不是唯一的,每个组都有多个值,所以你必须选择你想要的那个(不是在所有的DBMS中,MySQL允许它,它会随机选择)一个值)。
根据您的示例,我想您需要第一个ID
,因此MIN()
是最佳选择:
SELECT
min(bpq.Id),
b.BatchCode,
bpq.PartId,
bpq.Hkid
FROM
BoxPartsQuantity bpq
JOIN
Batch b
ON
bpq.BatchId = b.Id
WHERE
PartId = 1
GROUP BY
b.BatchCode,
bpq.Hkid,
bpq.PartId
答案 2 :(得分:1)
以下查询将提供所需的结果: -
SELECT
distinct min(bpq.Id) over(partition by b.BatchCode,bpq.Hkid),
b.BatchCode,
bpq.PartId,
bpq.Hkid
FROM
BoxPartsQuantity bpq
JOIN
Batch b
ON
bpq.BatchId = b.Id
WHERE bpq.PartId = 1
答案 3 :(得分:0)
您遇到的错误告诉我们,选择列列表中未包含在聚合函数中的每一列也应放在Group By中。
除了@Giorgos Betsos答案旁边的要求,您还可以使用不再需要使用Group By的Row_Number,如下所示:
SELECT Id ,
BatchCode ,
PartId ,
Hkid
FROM ( SELECT ROW_NUMBER() OVER ( PARTITION BY b.BatchCode ORDER BY bpq.Id ) AS Rn ,
bpq.Id ,
b.BatchCode ,
bpq.PartId ,
bpq.Hkid
FROM BoxPartsQuantity bpq
JOIN Batch b ON bpq.BatchId = b.Id
WHERE PartId = 1
) AS K
WHERE Rn = 1;
在上面的查询和内部子查询中,我们首先为每个记录分配行号。为每个不同的BatchCode重置此行号,并且将根据Id列对此行号进行排序。在分配行号后,我们在外部查询中过滤行号等于1。我们使用子查询分配行号并在外部查询中过滤它的原因是,Row_number不能放在查询的Where部分内。