需要 return 一个在 sql 服务器中具有开始和结束的 ID

Need to return an ID which has start and END in sql server

我有一个场景,我需要找到其中只有开始和结束的 ID。下面是table供参考。

Declare @T Table ( ID int, Name varchar(100))

Insert into @T values (1,'Start')
Insert into @T values (1,'END')
Insert into @T values (1,'Stuart')
Insert into @T values (1,'robin')
Insert into @T values (2,'Start')
Insert into @T values (2,'END')
Insert into @T values (3,'Start')
Insert into @T values (4,'END')

我希望输出为:

ID 姓名
2 开始
2 结束

我想要那些只有开头和结尾的ID。

到目前为止我尝试了什么:

SELECT * FROM @T t 
WHERE EXISTS (SELECT * FROM @T WHERE id = t.id AND name = 'start')
AND EXISTS (SELECT * FROM @T WHERE id = t.id AND name = 'END')

但我的查询也给出了 ID 1。

谁能帮我解决这个问题。

你能试试这个吗?请注意我在 sql 的末尾添加了整理命令。 SQL Server check case-sensitivity?

SELECT * FROM @T t 
WHERE EXISTS (SELECT * FROM @T WHERE id = t.id AND name = 'start' COLLATE SQL_Latin1_General_CP1_CS_AS)
AND EXISTS (SELECT * FROM @T WHERE id = t.id AND name = 'END' COLLATE SQL_Latin1_General_CP1_CS_AS)

我想你的问题是记录 1 中也有一个 'Stuart'?

因此,您可以在 WHERE 中进行类似的检查,例如,

SELECT * FROM @T t 
WHERE EXISTS (SELECT * FROM @T WHERE id = t.id AND name = 'start')
AND EXISTS (SELECT * FROM @T WHERE id = t.id AND name = 'END')
AND NOT EXISTS (SELECT * FROM @T WHERE id = t.id AND name NOT IN ('start','END'))

请注意,您可能需要考虑

  • 如果您有两行 'start' 行或两行 'end' 行(例如,start-start-end),会发生什么情况?你甚至可以有两个 'start' 行(例如 start-start)吗?
  • 如果您有 blank/NULL(例如 start-NULL-end)会怎样?

编辑:删除“如果它们出现故障会怎样(例如,end-start)?”作为一个问题,因为根本没有对数据进行排序(例如,甚至没有隐式排序)。

您可以使用 CTE 来获得分组计数和总计数为 2。

Declare @T Table ( ID int, Name varchar(100))

Insert into @T values (1,'Start')
Insert into @T values (1,'END')
Insert into @T values (1,'Stuart')
Insert into @T values (1,'robin')
Insert into @T values (2,'Start')
Insert into @T values (2,'END')
Insert into @T values (3,'Start')
Insert into @T values (4,'END')

;WITH CTE_Total_StartEnd AS
(
select id, count(*) AS Total_Cnt
, COUNT( case when Name IN ('Start') THEN 1 END) as start_cnt 
, COUNT( case when Name IN ('End') THEN 1 END) as end_cnt 
from @t
group by id
having  COUNT( case when Name IN ('Start') THEN 1 END) =1 and
COUNT( case when Name IN ('End') THEN 1 END) = 1  and
count(*) = 2
)
SELECT t.* from @t t
inner join CTE_Total_StartEnd as c 
ON c.id = t.id
+----+-------+
| ID | Name  |
+----+-------+
|  2 | Start |
|  2 | END   |
+----+-------+

您也可以通过使用分组功能来完成此操作,如下所示

WITH cte AS 
(
SELECT 1 AS id , 'Start' AS name 
UNION ALL 
SELECT 1  AS id ,'END'  AS name 
UNION ALL
SELECT 1 AS id ,'Stuart'  AS name
UNION ALL
SELECT 1 AS id ,'robin'  AS name  
UNION ALL
SELECT 2  AS id ,'Start'  AS name 
UNION ALL
SELECT 2 AS id ,'END'  AS name
UNION ALL
SELECT 3 AS id ,'Start'  AS name  
UNION ALL
SELECT 4 AS id ,'END'  AS name 
)
SELECT T.ID,SUM(T.VAL)AS SUM
FROM 
(
SELECT  id,name , CASE WHEN name='Start' THEN 1
                       WHEN name='END' THEN  2
                       ELSE 3
                  END AS VAL 
                    
FROM cte 
)T 
GROUP BY T.ID 
HAVING SUM(T.VAL) =3