【问题标题】:Need to return an ID which has start and END in sql server需要在 sql server 中返回一个有 start 和 END 的 ID
【发布时间】:2021-01-16 20:11:59
【问题描述】:

我有一个场景,我需要找到其中只有 start 和 END 的 ID。下表供参考。

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 server 不区分大小写吗?因为默认情况下它是。您可以要求管理员将其关闭并重试。或者你可以使用dbo.InitCap()函数来匹配Start。
  • 不区分大小写
  • 在这种情况下,您可以使用COLLATE 使其工作。请在答案中使用 sql 并告诉我。
  • @KoushikRoy 与否。当然不。这不是排序规则问题,而是一个古怪的查询。打破整个数据库的工作方式不是解决方案。更改数据库的排序规则也不会更改现有的列排序规则。强制排序会阻止使用任何现有索引。此外,区分大小写的搜索将匹配end 和END 而不会出现任何问题。 区分大小写搜索可以绕过记录
  • 我不知道拥有一个不区分大小写的数据库是否是个好主意。但一定有人让 MS 想通了。

标签: sql sql-server sql-server-2008


【解决方案1】:

您也可以使用 group by 函数来做到这一点,如下所示

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

【讨论】:

    【解决方案2】:

    您可以通过 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   |
    +----+-------+
    

    【讨论】:

      【解决方案3】:

      我想你的问题是记录 1 也有一个“斯图尔特”?

      因此,您可以在 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'))
      

      请注意,您可能需要考虑

      • 如果您有两个“开始”行或两个“结束”行(例如,开始-开始-结束),会发生什么情况?你甚至可以有两个“开始”行(例如,开始-开始)吗?
      • 如果您有一个空白/NULL(例如,start-NULL-end)会发生什么?

      编辑:删除了“如果它们出现故障(例如,结束开始)会发生什么?”作为一个问题,因为数据中根本没有排序(例如,甚至没有隐式排序)。

      【讨论】:

      • 请注意,如果满足数据要求,@Pwilcox 的另一个答案比我上面的答案更有效(因为只需要一次扫描)。最佳答案很大程度上取决于您如何回答上述问题。
      【解决方案4】:

      你能试试这个吗?请注意我在 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)
      

      【讨论】:

      • Msg 156, Level 15, State 1, Line 21 关键字“COLLATE”附近的语法不正确。
      • 你能试试这个。稍后我会返回正确的 sql,因为我现在无法测试。
      • 强制区分大小写的排序规则会错过所有Start记录。它会产生一个更大的问题,而不是解决当前的问题。强制排序规则会阻止服务器使用任何索引,因此此查询将导致全表扫描
      • 这只是 cmets 中的一个建议,而不是我回答的一部分。正如我所说,我需要对此进行测试以确保它有效,但它会给出一个想法。
      猜你喜欢
      • 2018-08-14
      • 1970-01-01
      • 2021-12-22
      • 1970-01-01
      • 2011-05-05
      • 2019-05-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多