我正在尝试从表中获取结果,使得它们受到类似字段值的数量的限制。例如,以下是一些示例记录:
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”)。
答案 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')