Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/84.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 选择来自首次客户的订单_Sql_Sql Server_Select - Fatal编程技术网

Sql 选择来自首次客户的订单

Sql 选择来自首次客户的订单,sql,sql-server,select,Sql,Sql Server,Select,我需要帮助构建一个SQL查询,该查询返回仅订购过一次的客户的订单 表和相关字段如下所示: Order Customer ------- ----------- orderId customerId orderDate customerId etc. 我正在查找订单记录的结果集,其中只有一个客户id出现。对于以下数据集 [orderId] [customerId] [ord

我需要帮助构建一个SQL查询,该查询返回仅订购过一次的客户的订单

表和相关字段如下所示:

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函数。