2013-06-02 52 views
1
IF object_id('tempdb..#A') IS NOT NULL DROP TABLE #A 
IF object_id('tempdb..#B') IS NOT NULL DROP TABLE #B 
CREATE TABLE #A (fname varchar(20), lname varchar(20)) 
CREATE TABLE #B (fname varchar(20), lname varchar(20)) 

INSERT INTO #A 
SELECT 'Kevin', 'XP' 
UNION ALL 
SELECT 'Tammy', 'Win7' 
UNION ALL 
SELECT 'Wes', 'XP' 
UNION ALL 
SELECT 'Susan', 'Win7' 
UNION ALL 
SELECT 'Kevin', 'Win7' 


SELECT * FROM #A 

INSERT INTO #B 
SELECT a.fname, a.lname FROM #A a 
WHERE a.fname NOT IN (SELECT fname from #B) 

SELECT * FROM #B 

DELETE FROM #B 
INSERT INTO #B 
SELECT a.fname, a.lname FROM #A a 
LEFT OUTER JOIN #B b ON a.fname = b.fname 
WHERE a.fname NOT IN (SELECT fname from #B) 

SELECT * FROM #B 

这两个示例都将所有5条记录复制到新表中。将记录从一张表复制到另一张没有重复记录

我只想看到一个独特的名字,所以只有一个凯文应该出现。

为什么不这些工作,或者有更好的方法来做到这一点?

这似乎是这样一个简单的事情。

+1

但哪个'凯文'应该进入新表? –

+0

Windows7如果同时存在 – kevro

+0

为什么选择Windows7?也许你可以发布表应该看起来像什么(以及为什么) – Rob

回答

2

这将创建行具有独特FNAME和采取的Win7是否Win7和XP都存在。

INSERT INTO #B 
SELECT a.fname, MIN(a.lname) 
FROM #A a 
GROUP BY a.fname 
+0

谢谢。我没有意识到MIN()也适用于字符串。在我上面的评论中,我使用CASE语句转换为数字,然后选择所需的数字。这很容易。 – kevro

1

按照意见,因为WX之前,那么你应该能够做到

INSERT INTO #B 
SELECT fname, lname 
FROM (
    SELECT fname, lname, 
      ROW_NUMBER() OVER(PARTITION BY fname ORDER BY lname) r 
    FROM #A 
) t 
WHERE r=1 

demo

+0

我喜欢这个,但MIN(lname)更简单。 Thx – kevro

1

回答你的问题,你为什么不你的查询工作?

INSERT INTO #B 
SELECT a.fname, a.lname FROM #A a 
WHERE a.fname NOT IN (SELECT fname from #B) 

该操作通过两种不同的操作进行评估。首先,查询的SELECT部分​​被执行。它返回一个表格。在这种情况下#B是空的,因此#A中的每个元组都将成为这个结果的一部分。然后,一旦计算出该结果,就将该结果插入到#B中。 #B将结束为#A的副本。

DBMS不会插入一个元组,然后重新评估#A的下一个元组的查询,因为您的问题似乎暗示了这一点。插入操作始终在查询完成后进行。

如果您的目标是将#A中的元组插入到#B中,但没有重复项,则有很多方法可以做到这一点。其中之一是:

INSERT INTO #B SELECT distinct * from #A; 

--dmg

+0

INSERT INTO #B SELECT DISTINCT仍然复制了5条记录。 – kevro

+0

对不起,我误解了你的问题。我以为你想要独特的元组,不能区分只有一个属性。我同意插入GROUP by是最好的解决方案。 – dmg

0

只需使用DISTINCT在选择查询:

INSERT INTO TARGET_TABLE 
SELECT DISTINCT * FROM 
(
    -- some big query 
) x 
相关问题