我需要将数据从一个表传输到另一个表。第二个表有一个主键约束(第一个没有约束)。它们具有相同的结构。我想要的是从表A中选择所有行并将其插入表B而不包含重复行(如果一行是0重复,我只想采取我找到的第一行)
示例:
MyField1 (PK) | MyField2 (PK) | MyField3(PK) | MyField4 | MyField5
----------
1 | 'Test' | 'A1' | 'Data1' | 'Data1'
2 | 'Test1' | 'A2' | 'Data2' | 'Data2'
2 | 'Test1' | 'A2' | 'Data3' | 'Data3'
4 | 'Test2' | 'A3' | 'Data4' | 'Data4'
如您所见,第二行和第三行获得了相同的pk键,但MyField4和MyField5中的数据不同。所以,在这个例子中,我希望有第一,第二和第四行。不是第三个,因为它是第二个的重复(即使MyField4和MyField5包含不同的数据)。
如何通过一次选择来实现这一目标?
THX
答案 0 :(得分:4)
首先,您需要定义使行成为“第一”的内容。我将构成一个任意定义,您可以根据需要更改SQL。对于这个例子,我假设“first”是MyField4的最低值,如果它们等于MyField5的最低值。它还说明了所有5列相同的可能性。
SELECT DISTINCT
T1.MyField1,
T1.MyField2,
T1.MyField3,
T1.MyField4,
T1.MyField5
FROM
MyTable T1
LEFT OUTER JOIN MyTable T2 ON
T2.MyField1 = T1.MyField1 AND
T2.MyField2 = T1.MyField2 AND
T2.MyField3 = T1.MyField3 AND
(
T2.MyField4 > T1.MyField4 OR
(
T2.MyField4 = T1.MyField4 AND
T2.MyField5 > T1.MyField5
)
)
WHERE
T2.MyField1 IS NULL
如果您还要考虑在源表中没有重复但在目标表中已存在的PK,那么您也需要考虑到这一点。
答案 1 :(得分:3)
不知道如何知道新表中第2行和第3行中的哪一行,但在mysql中你可以简单地说:
insert ignore into new_table (select * from old_table);
PK不允许插入重复的条目。
答案 2 :(得分:2)
你的数据库是什么?在Oracle中你可以说
SELECT FROM your_table
WHERE rowid in
(SELECT MIN(rowid)
FROM your_table
GROUP BY MyField1, MyField2, MyField3);
请注意,具有相同PK的哪一行将被视为“第一”,这有点不确定。如果您需要强制执行特定订单,则需要另外对其他列进行排序。
答案 3 :(得分:1)
这取决于你在寻找什么。
使用JOIN
+ WHERE NULL
,NOT IN
和NOT EXISTS
之间存在很大差异,包括性能,这对于较大的数据集更为重要。
(见NOT IN vs. NOT EXISTS vs. LEFT JOIN / IS NULL。)
链接文章中显示的三种方法非常简单。
答案 4 :(得分:0)
CREATE TABLE #A(
ID INTEGER IDENTITY,
[MyField1] [int] NULL,
[MyField2] [varchar](10) NULL,
[MyField3] [varchar](10) NULL,
[MyField4] [varchar](10) NULL,
[MyField5] [varchar](10) NULL
)
INSERT INTO #A (MyField1,MyField2,MyField3,MyField4,MyField5) SELECT * FROM A
insert into B
select MyField1,MyField2,MyField3,MyField4,MyField5 from #A a1
where not exists (select id from #A a2 where a2.MyField1 = a1.MyField1 and a2.ID < a1.ID)
DROP TABLE #A
OR
insert into b
select distinct * from a a1
where not exists (
select a2.MyField1 from a a2 where a1.MyField1 = a2.MyField1 and
(a1.MyField2 < a2.MyField2 or a1.MyField3 < a2.MyField3
or a1.MyField4 < a2.MyField5 or a1.MyField5 < a2.MyField5))