2010-08-26 17 views
3

我有一个表People(First_Name,Last_Name)。此表具有与示例中相同的记录(并非所有行都重复):SQL通过多列忽略列顺序从表中选择不同行(重要性)

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

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

谢谢。

+0

SQL的什么版本? – Tobiasopdenbrouw 2010-08-26 08:51:09

+0

它是MySQL 5.1。谢谢。 – 2010-08-26 08:57:16

回答

5

只需选择一个排序和跨越每个人都使用它。然后使用联盟,无论如何将消除重复

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

不错的。你会在RL发布的答案中使用这个版本吗? (为什么?) – Tobiasopdenbrouw 2010-08-26 09:03:12

+0

就是这样。谢谢! – 2010-08-26 09:05:52

+1

@Tobias - 嗯,这是我想到的第一个答案,我没有看到其他人发布过类似的消息。我会注意到你的确取决于这些列中没有出现的特殊字符(“”),这些字符可能相关也可能不相关。根据表的大小和优化器的智能,这可能会导致对表的两次扫描,但我认为你的问题也是一样的 - 子查询将扫描整个表。 – 2010-08-26 09:10:29

1

对不起被missundertanding在第一次尝试你的问题......

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 
+1

你是否无视'玛丽布什'应与'布什玛丽'分组? – Tobiasopdenbrouw 2010-08-26 08:53:05

+0

是的,我认为他是... – 2010-08-26 08:54:57

+0

不需要。first_name和last_name属性需要提醒他们的逻辑。在最终答案中,约翰史密斯和史密斯约翰最初的记录必须有约翰史密斯记录。 – 2010-08-26 09:00:30

3

这是一种使用几乎任何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 
     ) 
0

下面是一个使用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> 
0

我认为这可能在MS-SQL工作

SELECT * FROM人民

其中(姓+ “” +姓氏)<>(名字+ “” +姓)

0

另一个sugestion

临时表:

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