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 つのレコードすべてを新しいテーブルにコピーします。

一意の fname を 1 つだけ表示したいので、Kevin は 1 つだけ表示する必要があります。

これらが機能しないのはなぜですか、またはそれを行うためのより良い方法はありますか?

そんな単純なことのように思えます。

4

4 に答える 4

2

これにより、一意の fname を持つ行が作成され、Win7 と XP の両方が存在する場合は Win7 が使用されます。

INSERT INTO #B
SELECT a.fname, MIN(a.lname) 
FROM #A a
GROUP BY a.fname
于 2013-06-03T01:25:26.897 に答える
1

あなたの質問に答えて、クエリが機能しないのはなぜですか?

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

この操作は、2 つの異なる操作で評価されます。最初に、クエリの SELECT 部分が実行されます。テーブルを返します。そのような時点で #B は空であるため、#A のすべてのタプルがこの結果の一部になります。次に、この結果が計算されると、この結果が #B に挿入されます。#B は #A のコピーではなくなります。

あなたの質問が示唆しているように、DBMSは1つのタプルを挿入せず、#Aの次のタプルのクエリを再評価しません。挿入は、クエリが完全に評価された後に常に行われます。

あなたの目標が #A のタプルを重複せずに #B に挿入することである場合、それを行う方法はたくさんあります。それらの1つは次のとおりです。

INSERT INTO #B SELECT distinct * from #A;

--dmg

于 2013-06-03T01:15:00.637 に答える
0

選択クエリに対して DISTINCT を使用するだけです。

INSERT INTO TARGET_TABLE
SELECT DISTINCT * FROM
(
     -- some big query
) x
于 2013-06-03T01:25:11.490 に答える