我有一个包含以下数据的Sales表:
| SalesId | CustomerId | Amount |
|---------|------------|--------|
| 1 | 1 | 100 |
| 2 | 2 | 75 |
| 3 | 1 | 30 |
| 4 | 3 | 49 |
| 5 | 1 | 93 |
我想在此表中插入一列,告诉我们客户购买的次数。所以它会像:
| SalesId | CustomerId | Amount | SalesNum |
|---------|------------|--------|----------|
| 1 | 1 | 100 | 1 |
| 2 | 2 | 75 | 1 |
| 3 | 1 | 30 | 2 |
| 4 | 3 | 49 | 1 |
| 5 | 1 | 93 | 3 |
所以我可以看到在salesId = 5中,这是customerId = 1的第3个事务。如何编写这样的查询来插入/更新这样的列?我在使用MS SQL,但我也对MYSQL解决方案感兴趣,如果我将来需要这样做的话。
谢谢。
PS。表格格式的道歉。无法弄清楚如何很好地格式化它。
答案 0 :(得分:2)
使用子查询,
Select *, (Select count(customerid)
from ##tmp t
where t.salesid <= s.salesid
and t.customerid = s.customerid)
from ##tmp s
答案 1 :(得分:1)
试试这个 -
SELECT SalesId, CustomerId, Amount,
SalesNum = ROW_NUMBER() OVER (PARTITION BY CustomerId ORDER BY SalesId)
FROM YOURTABLE
答案 2 :(得分:1)
您需要ROW_NUMBER()来指定序列号。我强烈建议您不要存储此值,因为您需要在每次更新时重新计算它,相反,如果您需要定期查看,最好创建一个视图:
CREATE VIEW dbo.SalesWithRank
AS
SELECT SalesID,
CustomerID,
Amount,
SalesNum = ROW_NUMBER() OVER(PARTITION BY CustomerID ORDER BY SalesID)
FROM Sales;
GO
<强> SQL Server Example on SQL Fiddle 强>
ROW_NUMBER()
不会在同一组中分配重复项,例如如果您根据Amount
分配行,并且同一客户有两个销售额均为100,那么在ROW_NUMBER()
中没有任何其他订购条件的情况下,它们将没有相同的SalesNum功能他们将被随机分类。如果您希望具有相同金额的销售额具有相同的SalesNum
,则您需要使用RANK
或DENSE_RANK
。 DENSE_RANK
在序列中没有间隙,例如1, 1, 2, 2, 3
,而RANK
将从相应位置开始,例如1, 1, 3, 3, 5
。
如果您必须将此作为更新,那么您可以使用:
WITH CTE AS
( SELECT SalesID,
CustomerID,
Amount,
SalesNum,
NewSalesNum = ROW_NUMBER() OVER(PARTITION BY CustomerID ORDER BY SalesID)
FROM Sales
)
UPDATE CTE
SET SalesNum = NewSalesNum;
<强> SQL Server Update Example on SQL Fiddle 强>
MySQL没有排名函数,因此您需要使用局部变量来跟踪前一行的值来获得排名。这在视图中是不允许的,因此您只需要在需要行号的地方重复此逻辑:
SELECT s.SalesID,
s.Amount,
@r:= CASE WHEN @c = s.CustomerID THEN @r + 1 ELSE 1 END AS SalesNum,
@c:= CustomerID AS CustomerID
FROM Sales AS s
CROSS JOIN (SELECT @c:= 0, @r:= 0) AS var
ORDER BY s.CustomerID, s.SalesID;
这里的顺序是至关重要的,这意味着为了在不影响排名的情况下对结果进行排序,您需要使用子查询:
SELECT SalesID,
Amount,
CustomerID,
SalesNum
FROM ( SELECT s.SalesID,
s.Amount,
@r:= CASE WHEN @c = s.CustomerID THEN @r + 1 ELSE 1 END AS SalesNum,
@c:= CustomerID AS CustomerID
FROM Sales AS s
CROSS JOIN (SELECT @c:= 0, @r:= 0) AS var
ORDER BY s.CustomerID, s.SalesID
) AS s
ORDER BY s.SalesID;
<强> MySQL Example on SQL Fiddle 强>
同样,我建议不要存储值,但如果你必须在MySQL中使用:
UPDATE Sales
INNER JOIN
( SELECT s.SalesID,
@r:= CASE WHEN @c = s.CustomerID THEN @r + 1 ELSE 1 END AS NewSalesNum,
@c:= CustomerID AS CustomerID
FROM Sales AS s
CROSS JOIN (SELECT @c:= 0, @r:= 0) AS var
ORDER BY s.CustomerID, s.SalesID
) AS s2
ON Sales.SalesID = s2.SalesID
SET SalesNum = s2.NewSalesNum;