Sql 选择来自首次客户的订单
我需要帮助构建一个SQL查询,该查询返回仅订购过一次的客户的订单 表和相关字段如下所示:Sql 选择来自首次客户的订单,sql,sql-server,select,Sql,Sql Server,Select,我需要帮助构建一个SQL查询,该查询返回仅订购过一次的客户的订单 表和相关字段如下所示: Order Customer ------- ----------- orderId customerId orderDate customerId etc. 我正在查找订单记录的结果集,其中只有一个客户id出现。对于以下数据集 [orderId] [customerId] [ord
Order Customer
------- -----------
orderId customerId
orderDate
customerId
etc.
我正在查找订单记录的结果集,其中只有一个客户id出现。对于以下数据集
[orderId] [customerId] [orderDate] [etc.]
---------- ------------ ------------ ------------
o1 c1 1/1/14 foo
o2 c2 1/1/14 baz
o3 c3 1/3/14 bar
o4 c2 1/3/14 wibble
我希望结果是正确的
[orderId] [orderDate] [etc.]
--------- ----------- ------
o1 1/1/14 foo
o3 1/3/14 bar
由于c2已订购两次,因此订单o2和o4被取消
任何帮助都将不胜感激
对不起,我没有把我失败的尝试放进去。这就是我试过的
SELECT customerId,
orderId,
orderDate,
Count(*)
FROM Orders
GROUP BY orderId,
orderDate,
customerID
HAVING Count(*) = 1
ORDER BY orderId
它似乎返回所有订单。这将列出订单表中的所有首次客户 为了返回所有额外的列,您需要将它们包装在一个聚合中,例如MIN/MAX
使用哪一行是任意的,因为无论如何每个组只有一行。这确实假设表中的所有列都是对此类聚合有效的数据类型,但是不有效的数据类型示例是BIT或XML,请尝试以下假设SQL Server 2005+:
;WITH CTE AS
(
SELECT *,
N = COUNT(*) OVER(PARTITION BY customerId)
FROM Orders
)
SELECT *
FROM CTE
WHERE N = 1
SELECT *
FROM ( SELECT *,
N = COUNT(*) OVER(PARTITION BY customerId)
FROM Orders) T
WHERE N = 1
因为有时候,与复杂的CTE相比,更倾向于采用平庸的方法,所以如果需要,可以使用派生表,但因为它使用over子句,所以仍然需要SQL Server 2005+:
;WITH CTE AS
(
SELECT *,
N = COUNT(*) OVER(PARTITION BY customerId)
FROM Orders
)
SELECT *
FROM CTE
WHERE N = 1
SELECT *
FROM ( SELECT *,
N = COUNT(*) OVER(PARTITION BY customerId)
FROM Orders) T
WHERE N = 1
或者,如果您使用的是早于2005年版本的SQL Server,则可以使用GROUP BY/HAVING COUNT*=1方法查找只有1个订单的客户,然后重新连接到Orders表,不需要在所有列中使用聚合函数:
SELECT o.*
FROM Orders o
JOIN
( SELECT customerId
FROM Orders
GROUP BY customerId
HAVING COUNT(*) = 1
) c
ON c.customerId = o.customerId ;
或者使用不存在,不需要计数,即使在MySQL中也可以使用:
SELECT o.*
FROM Orders o
WHERE NOT EXISTS
( SELECT 1
FROM Orders c
WHERE c.customerId = o.customerId
AND c.orderId <> o.orderId
) ;
这不一定是一个完整的答案。从来没有。堆栈溢出从来就不是必需的。聚合函数是关键。ClayDavis今天学到了很多。@ClayDavis请注意,如果你在没有“当然”的情况下聚合每一列,它们不会全部来自同一行,除非完全是巧合。一种更可预测和确定的方法是使用排序函数,如。@AaronBertrand中的计数*=1,在这种情况下,对吗?+1这完全满足了要求@Lamak的解决方案优于IMHO,因为它更灵活,但是这个解决方案是正确的。您失败的尝试可能会返回所有订单,因为orderDate和orderID位于GROUP BY子句中。如果要按customerID计数订单,则只能按customerID分组。这是有道理的,但如果删除orderID,我会收到此错误消息:“orders.orderID”列在选择列表中无效,因为它既不包含在聚合函数中,也不包含在GROUP by子句中。对;他们也不能在选择区。如果您希望在单个查询中执行此操作,请参阅下面Lamak的建议。最后两个示例最适合我的情况,因为聚合函数阻止我在另一个表上执行Stuff函数。