使用TSQL按字段值限制结果

时间:2015-12-17 05:37:22

标签: sql sql-server tsql

我正在尝试从表中获取结果,使得它们受到类似字段值的数量的限制。例如,以下是一些示例记录:

FieldValue (nvarchar)
----------
id1/mode3/path
id2/mode2/path
id3/mode3/path
id4/mode1/path
id5/mode3/path
id6/mode2/path
id7/mode2/path
id8/mode3/path

在这种情况下,我只想要每种模式最多2条记录,因此结果应为:

id1/mode3/path
id2/mode2/path
id3/mode3/path
id4/mode1/path
id6/mode2/path

如何在TSQL(SQL Server 2012)中执行此操作?

[更新] 注意:ID,模式和路径不是单独的字段。它们是名为FieldValue的字段中的连接文本值(例如“id1 / mode3 / path”)。

4 个答案:

答案 0 :(得分:2)

您可以使用窗口函数和字符串操作函数来分割数据:

<div class="containner">
    
        <img src="images/left_image.jpg" width="100" height="100" /> 
    
        <img src="images/right_image.jpg" width="100" height="100" />
       
</div>

LiveDemo

输出:

WITH cte AS
( SELECT 
       FieldValue
      ,[id]        = LEFT(FieldValue, CHARINDEX('/', FieldValue)-1)
      ,[mode]      = SUBSTRING(FieldValue,
                               CHARINDEX('/', FieldValue)+1,
                               CHARINDEX('/',RIGHT(FieldValue,LEN(FieldValue)
                               -CHARINDEX('/', FieldValue)))-1)
  FROM #tab
), cte2 AS
(
  SELECT FieldValue, r = ROW_NUMBER() OVER (PARTITION BY mode ORDER BY id)
  FROM cte
)
SELECT FieldValue
FROM cte2
WHERE r <= 2
ORDER BY FieldValue;

答案 1 :(得分:2)

Lad2025的答案完成了这项工作,但如果可能的话,我会考虑改进你的表格设计(架构)。

为了避免计算这些子串并基于它进行排序(对于大数据而言是昂贵的),您可以向表中添加新列。插入FieldValue时可以计算它们,如果不可能,则可以将它们添加为持久计算列:

id NVARCHAR(10) AS LEFT(FieldValue, CHARINDEX('/', FieldValue)-1) PERSISTED,
mode NVARCHAR(10) AS SUBSTRING(FieldValue,
                               CHARINDEX('/', FieldValue)+1,
                               CHARINDEX('/',RIGHT(FieldValue,LEN(FieldValue)
                               -CHARINDEX('/', FieldValue)))-1) PERSISTED

因此,查询大大简化了:

;WITH cte AS
(
  SELECT FieldValue, r = ROW_NUMBER() OVER (PARTITION BY mode ORDER BY id)
  FROM yourtable
)
SELECT FieldValue
FROM cte 
WHERE r <= 2
ORDER BY FieldValue;

此设计还允许索引添加的列以获得更高的性能。

答案 2 :(得分:1)

with cte
as
(
      select row_number() over(partition by mode order by mode) as cnt,*
      from FieldValue
)
select id,mode,path
from cte 
where cnt <= 2

尝试此查询。

答案 3 :(得分:1)

试,

select md from(
select md,row_number() over (partition by replace(stuff(md,1,CHARINDEX('/',md),''),
(stuff(md,1,CHARINDEX('/',md,CHARINDEX('/',md)+1)-1,'')),'')
order by left(md,CHARINDEX('/',md))) as r from @t) t
where r<=2 order by md

示例数据

declare @t table(md varchar(50)) insert into @t values
('id1/mode3/path'),
('id2/mode2/path'),
('id3/mode3/path'),
('id4/mode1/path'),
('id5/mode3/path'),
('id6/mode2/path'),
('id7/mode2/path'),
('id8/mode3/path')