每组返回前3行

时间:2012-07-20 19:35:03

标签: sql sql-server-2000

当我做出这个选择它显示结果所有“车辙”与它的电话号码,我的问题   是每个“车辙”有近10个电话号码,我只需要3个电话号码   每个“车辙”,我尝试使用TOP,但只显示所有表的前3行而不是   第一行是“rut”,我如何才能将TOP仅用于行“rut”而不是全部   表

Select Distinct  
t1.rut_cliente as rut_cliente,
t1.nro_fono  as numero 
--Into #tmp_numeros
From dat_clientes_sucursales_contactos_telefonos t1,dat_rut_clientes t2
where  t1.rut_cliente = t2.rut_cliente 
and cod_prioridad = 1

这是我对此查询的结果:

  Rut_cliente   Nro_fono 
  60506000-5    2046840
  60506000-5    3507935
  60506000-5    4106886
  60506000-5    5440000
  60506000-5    5445000
  81698900-0    2373281
  81698900-0    3541342
  81698900-0    3541438
  81698900-0    3541518
  81698900-0    3542101

这就是我想要的:

  Rut_cliente   Nro_fono 
  60506000-5    2046840
  60506000-5    3507935
  60506000-5    4106886
  81698900-0    2373281
  81698900-0    3541342
  81698900-0    3541438

提前感谢。

3 个答案:

答案 0 :(得分:7)

该问题最初标记为SQL Server 2008,您可以使用公用表表达式执行此操作:

;WITH x AS 
 (
   SELECT Rut_cliente, Nro_fono, rn = ROW_NUMBER()
     OVER (PARTITION BY Rut_cliente ORDER BY Nro_fono)
   FROM dbo.dat_clientes_sucursales_contactos_telefonos AS t1
   INNER JOIN dbo.dat_rut_clientes AS t2
   ON t1.rut_cliente = t2.rut_cliente
   WHERE cod_prioridad = 1
)
SELECT Rut_cliente, Nro_fono FROM x
WHERE rn <= 3
ORDER BY Rut_cliente, Nro_fono;

其他评论:

  • 请不要使用table, table语法。使用正确的INNER JOIN。我explain why here
  • 请在内部查询中添加适当的别名,以便人们知道哪些列来自t1,哪些列来自t2。

但是现在我们知道用户实际上正在使用SQL Server 2000.我认为这就是我在那里做的方式,但性能会变得非常糟糕。我不是100%肯定这是有效的(因为我再次猜测哪些列来自哪个表)。

SELECT x.rut_cliente, x.nro_fono, COUNT(*) FROM 
(
  SELECT t1.rut_cliente, t1.nro_fono
    FROM dat_clientes_sucursales_contactos_telefonos AS t1
    INNER JOIN dat_rut_clientes AS t2
    ON t1.rut_cliente = t2.rut_cliente
    WHERE cod_prioridad = 1
) AS x
INNER JOIN dat_clientes_sucursales_contactos_telefonos AS b
ON b.rut_cliente = x.rut_cliente
AND b.nro_fono <= x.nro_fono
GROUP BY x.rut_cliente, x.nro_fono
HAVING COUNT(*) <= 3
ORDER BY x.rut_cliente, x.Nro_fono;

答案 1 :(得分:5)

例如,ROW_NUMBER是一个窗函数,并返回由group by确定的每个分区的行号(类似于order by)。:

WITH CTE AS(
   SELECT t1.rut_cliente as rut_cliente, t1.nro_fono  as numero,
      RN = ROW_NUMBER()OVER(PARTITION BY Rut_cliente ORDER BY Nro_fono)
   FROM dbo.dat_clientes_sucursales_contactos_telefonos AS t1
   INNER JOIN dbo.dat_rut_clientes AS t2 ON t1.rut_cliente = t2.rut_cliente
   WHERE cod_prioridad = 1
)
SELECT rut_cliente as rut_cliente, nro_fono  as numero
FROM CTE
WHERE RN <= 3

答案 2 :(得分:0)

试试这个

;with CTE AS (
select Rut_cliente, Nro_fono , ROW_NUMBER() OVER 
(PARTITION BY Rut_cliente ORDER BY Nro_fono) rn
 FROM dbo.dat_clientes_sucursales_contactos_telefonos AS a
INNER JOIN dbo.dat_rut_clientes AS b
ON a.rut_cliente = b.rut_cliente
WHERE cod_prioridad = 1

)
SELECT * FROM CTE where rn <=3