【问题标题】:SQL SELECT distinct rows from a table by multiple columns ignoring columns order (significance)SQL SELECT 通过多个列从表中选择不同的行,忽略列顺序(意义)
【发布时间】:2010-08-26 08:47:33
【问题描述】:

我有一张桌子 People (First_Name, Last_Name)。该表的记录与示例中一样重复(并非所有行都重复):

First_Name  Last_Name
John        Smith
Alec        Baldwin
Smith       John
Angelo      Gordon
Mary        Bush
Bush        Mary

如何选择所有不同的人?在查询的最终输出中,John Smith 应该只出现一次(如果在最终查询中存在 John Smith 或 Smith John,则不是导入)。

谢谢。

【问题讨论】:

    标签: sql select


    【解决方案1】:

    只需选择一个排序并将其应用于每个人。然后使用一个可以消除重复的联合

    select FirstName,LastName from People where FirstName <= LastName
    union
    select LastName,FirstName from People where LastName < FirstName
    

    【讨论】:

    • 不错的一个。你会在 RL 中使用这个版本而不是我发布的答案吗? (为什么?)
    • @Tobias - 嗯,这是我想到的第一个答案,我没有看到其他人发布类似的帖子。我会注意到,您的确实取决于这些列中未出现的特殊字符(“”),这可能相关也可能不相关。根据表的大小和优化器的智能,这可能会导致对表进行两次扫描,但我认为您的问题存在相同的问题 - 我认为子查询将扫描整个表。
    • 干净的想法。竖起大拇指!也许它可能会出现性能问题,但我认为其他解决方案也会有更大的问题。
    • 感谢您的回答和澄清评论。
    【解决方案2】:

    这是使用几乎任何 SQL 风格的一种方法。

    DECLARE @Names TABLE (
      First_Name VARCHAR(32)
      , Last_Name VARCHAR(32)
    )  
    
    INSERT INTO @Names VALUES ('John', 'Smith')
    INSERT INTO @Names VALUES ('Alec', 'Baldwin')
    INSERT INTO @Names VALUES ('Smith', 'John')
    INSERT INTO @Names VALUES ('Angelo', 'Gordon')
    INSERT INTO @Names VALUES ('Mary', 'Bush')
    INSERT INTO @Names VALUES ('Bush', 'Mary')
    

    使用JOIN

    SELECT  n1.*
    FROM    @Names n1
            LEFT OUTER JOIN @Names n2 ON n2.First_Name = n1.Last_Name
                                         AND n2.Last_Name = n1.First_Name
                                         AND n2.First_Name < n1.First_Name
    WHERE   n2.First_Name IS NULL                                     
    

    NOT EXISTS

    SELECT  n1.*
    FROM    @Names n1
    WHERE   NOT EXISTS (
              SELECT  *  
              FROM    @Names n2 
              WHERE   n2.First_Name = n1.Last_Name
                      AND n2.Last_Name = n1.First_Name
                      AND n2.First_Name < n1.First_Name
            )
    

    【讨论】:

      【解决方案3】:

      抱歉,第一次尝试时误解了您的问题...

      WITH People (Firstname, Lastname)
      AS
      (
          SELECT 'John' AS Firstname, 'Smith' AS Lastname UNION
          SELECT 'John' AS Firstname, 'Smith' AS Lastname UNION
          SELECT 'Alec' AS Firstname, 'Baldwin' AS Lastname UNION
          SELECT 'Smith' AS Firstname, 'John' AS Lastname UNION
          SELECT 'John' AS Firstname, 'Smith' AS Lastname UNION
          SELECT 'Angelo' AS Firstname, 'Gordon' AS Lastname UNION
          SELECT 'Mary' AS Firstname, 'Bush' AS Lastname UNION
          SELECT 'Bush' AS Firstname, 'Mary' AS Lastname
      )
      SELECT p1.* FROM People p1 
      LEFT OUTER JOIN People p2 ON p2.Firstname = p1.Lastname AND p2.Lastname = p1.Firstname AND p2.Firstname < p1.Firstname 
      WHERE p2.Firstname IS NULL  
      

      【讨论】:

      • 您是否忽略了“Mary Bush”应该与“Bush Mary”分组?
      • 没有。 first_name 和 last_name 属性需要破坏它们的逻辑。在最终答案中,John Smith 和 Smith John 初始记录都必须有 John Smith 记录。
      • 对不起我的错。完全误解了这个问题。
      【解决方案4】:

      这是一个使用 Oracle 函数的解决方案。其他风格的 SQL 将具有相同或非常相似的功能:

      SQL> select * from t23
        2  /
      
      FIRST_NAME                     LAST_NAME
      ------------------------------ ------------------------------
      John                           Smith
      Alec                           Baldwin
      Smith                          John
      Angelo                         Gordon
      Mary                           Bush
      Bush                           Mary
      
      6 rows selected.
      
      SQL> select distinct least(first_name, last_name)
        2                  , greatest(first_name, last_name)
        3  from t23
        4  /
      
      LEAST(FIRST_NAME,LAST_NAME)    GREATEST(FIRST_NAME,LAST_NAME)
      ------------------------------ ------------------------------
      Alec                           Baldwin
      Bush                           Mary
      John                           Smith
      Angelo                         Gordon
      
      SQL> 
      

      【讨论】:

        【解决方案5】:

        我认为这可能适用于 MS-SQL

        从人物中选择 *

        哪里(名字+“,”+姓氏)(姓氏+“,”+名字)

        【讨论】:

          【解决方案6】:

          另一个建议

          临时表:

          DECLARE @Names TABLE (
            First_Name VARCHAR(32)
            , Last_Name VARCHAR(32)
          )  
          
          INSERT INTO @Names VALUES ('John', 'Smith')
          INSERT INTO @Names VALUES ('Alec', 'Baldwin')
          INSERT INTO @Names VALUES ('Smith', 'John')
          INSERT INTO @Names VALUES ('Angelo', 'Gordon')
          INSERT INTO @Names VALUES ('Mary', 'Bush')
          INSERT INTO @Names VALUES ('Bush', 'Mary')
          

          使用CASE

          SELECT DISTINCT 
              CASE WHEN First_Name <= Last_Name THEN First_Name ELSE Last_Name END AS First_Name,
              CASE WHEN First_Name <= Last_Name THEN Last_Name ELSE First_Name END AS Last_Name
          FROM @Names
          

          【讨论】:

            猜你喜欢
            • 2023-02-26
            • 2011-12-24
            • 1970-01-01
            • 1970-01-01
            • 2020-04-23
            • 2022-12-07
            • 2021-11-05
            • 1970-01-01
            • 2021-11-25
            相关资源
            最近更新 更多