Sql server SQL Server在显示整个表的同时对列中的不同项进行计数

Sql server SQL Server在显示整个表的同时对列中的不同项进行计数,sql-server,count,distinct,Sql Server,Count,Distinct,我最近遇到了一个关于计算行数的问题 我使用的表中有很多文章,每个都与一个运动相关,而这个运动又属于一个用户。通常,为了计算每个用户有多少不同的动作,我会这样做: SELECT Mov.Usuario, COUNT(DISTINCT Mov.MovID) FROM Mov WHERE Mov.Mov = 'Requisicion' GROUP BY Mov.Usuario 这给了我一张类似的表格: 但是,我还需要在这个表中包括每篇文章的数据,以及运动的ID,类似这样: SELECT Mov.U

我最近遇到了一个关于计算行数的问题

我使用的表中有很多文章,每个都与一个运动相关,而这个运动又属于一个用户。通常,为了计算每个用户有多少不同的动作,我会这样做:

SELECT Mov.Usuario, COUNT(DISTINCT Mov.MovID)
FROM Mov
WHERE Mov.Mov = 'Requisicion'
GROUP BY Mov.Usuario
这给了我一张类似的表格:

但是,我还需要在这个表中包括每篇文章的数据,以及运动的ID,类似这样:

SELECT Mov.Usuario, Mov.MovID, Art.Descripcion1
FROM Mov
INNER JOIN CompraD
ON Mov.ID = CompraD.ID
INNER JOIN Art
ON CompraD.Articulo = Art.Articulo
WHERE Mov.Mov = 'Requisicion'
AND Mov.FechaEmision BETWEEN 'ParameterA' AND 'ParameterB' -- This is the line added by the system

修剪结果以仅显示用户CGARCIA的行

有必要与其他表进行一些连接以获得第三列,因此。。。为了获得前三列,我运行了以下查询:

SELECT Mov.Usuario, Mov.MovID, Art.Descripcion1
FROM Mov
INNER JOIN CompraD
ON Mov.ID = CompraD.ID
INNER JOIN Art
ON CompraD.Articulo = Art.Articulo
WHERE Mov.Mov = 'Requisicion'
现在的问题是。。。如何获得第四列,该列计算每个用户有多少不同的MOVID?尝试在SELECT部件的末尾添加COUNT(DISTINCT Mov.MovID)并在查询的末尾按Mov.MovID添加组会抛出一个错误,即:

选择列表中的列“Mov.MovID”无效,因为它未包含在聚合函数中,或者

是的,它在中间被切断了。

另一个问题是,此SQL语句是从外部程序调用的,这将允许按日期筛选结果。为此,它会显示一个表单,询问开始和结束日期,并在查询末尾附加WHERE条件,如下所示:

SELECT Mov.Usuario, Mov.MovID, Art.Descripcion1
FROM Mov
INNER JOIN CompraD
ON Mov.ID = CompraD.ID
INNER JOIN Art
ON CompraD.Articulo = Art.Articulo
WHERE Mov.Mov = 'Requisicion'
AND Mov.FechaEmision BETWEEN 'ParameterA' AND 'ParameterB' -- This is the line added by the system
我无法控制这一点,也无法将参数添加到查询中,因为它们是由程序编写的。我可以让程序添加一个组在结束后的条件虽然

我尝试过使用数据获取表,并将其与包含行的表连接起来,但由于程序在最后添加了过滤条件,因此计数结果不会受到影响,并对所有行进行计数

我怎样才能避开这个问题呢?

试试这个:

SELECT Mov.Usuario, Mov.MovID, Art.Descripcion1, cntMov.CountCol
FROM Mov m1
INNER JOIN CompraD c ON m1.ID = c.ID
INNER JOIN Art a ON c.Articulo = a.Articulo
OUTER APPLY 
(
   SELECT COUNT(DISTINCT x.MovID) CountCol
   FROM Mov x
   WHERE x.Mov = m1.Mov
   GROUP BY x.Usuario
) cntMov
WHERE m1.Mov = 'Requisicion'
AND m1.FechaEmision BETWEEN 'ParameterA' AND 'ParameterB'
编辑:

SELECT Mov.Usuario, Mov.MovID, Art.Descripcion1,  
COUNT(*) OVER (PARTITION BY Mov.Usuario) Cnt
FROM Mov m1
INNER JOIN CompraD c ON m1.ID = c.ID
INNER JOIN Art a ON c.Articulo = a.Articulo   
WHERE m1.Mov = 'Requisicion'
AND m1.FechaEmision BETWEEN 'ParameterA' AND 'ParameterB'
试试这个:

SELECT Mov.Usuario, Mov.MovID, Art.Descripcion1, cntMov.CountCol
FROM Mov m1
INNER JOIN CompraD c ON m1.ID = c.ID
INNER JOIN Art a ON c.Articulo = a.Articulo
OUTER APPLY 
(
   SELECT COUNT(DISTINCT x.MovID) CountCol
   FROM Mov x
   WHERE x.Mov = m1.Mov
   GROUP BY x.Usuario
) cntMov
WHERE m1.Mov = 'Requisicion'
AND m1.FechaEmision BETWEEN 'ParameterA' AND 'ParameterB'
编辑:

SELECT Mov.Usuario, Mov.MovID, Art.Descripcion1,  
COUNT(*) OVER (PARTITION BY Mov.Usuario) Cnt
FROM Mov m1
INNER JOIN CompraD c ON m1.ID = c.ID
INNER JOIN Art a ON c.Articulo = a.Articulo   
WHERE m1.Mov = 'Requisicion'
AND m1.FechaEmision BETWEEN 'ParameterA' AND 'ParameterB'

为了处理不同的问题,请尝试以下方法(Plamen Ratchev的想法):


为了处理不同的问题,请尝试以下方法(Plamen Ratchev的想法):


这个想法有点奏效,但计数似乎没有考虑到最后添加的过滤器。我添加了一个条件,其中m1.MovID=203,理论上,我应该在count列中得到1,但我得到了6,这是拥有移动203的用户的移动总数。换句话说,CountCol列是在应用WHERE过滤器之前生成的。它每行返回1,由于它们都具有Usuario、MovID和Descripcion1的唯一组合。请尝试更新的解决方案,如果您说它们是唯一的,则应给出正确的计数。@ZoeStellan:count(DISTINCT)OVER()在SQL Server中确实不受支持。这正是您所需要的,而且可能没有其他方法适合您(假设查询不是可参数化的,而是由程序修改的)。这个想法有点奏效,但计数似乎没有考虑到最后添加的过滤器。我添加了一个条件,其中m1.MovID=203,理论上,我应该在count列中得到1,但我得到了6,这是拥有移动203的用户的移动总数。换句话说,CountCol列是在应用WHERE过滤器之前生成的。它每行返回1,由于它们都具有Usuario、MovID和Descripcion1的唯一组合。请尝试更新的解决方案,如果您说它们是唯一的,则应给出正确的计数。@ZoeStellan:count(DISTINCT)OVER()在SQL Server中确实不受支持。这正是您所需要的,并且可能没有其他方法适合您(假设查询不是可参数化的,而是由程序修改的)。您必须计算不同的ID吗?@AndriyM是的。与艺术表连接会在每个移动中产生多个项目,这意味着有多行具有相同的MovID。你必须计算不同的ID吗?@AndriyM是的。与Art表连接会在每个移动中产生多个项目,这意味着有多行具有相同的MovID。但是,我无法将日期筛选器放在它所属的位置。我将要使用查询的程序会在末尾添加该行,还可以选择添加一个GROUP BY。但是,这样我就无法将日期筛选器放在它所属的位置。我将在其中使用查询的程序在末尾添加该行,还可以选择添加一个groupby。