有没有办法只在第一次出现的记录

时间:2015-07-01 16:07:18

标签: sql sql-server

我正在加入两个表,或者更确切地说是一个查询和多个字段的子查询。因此,对于第一个查询中的每个PK,我可以从第二个子查询中获取一个或多个记录。有没有办法只从两个查询中返回TOP 1匹配?

示例:

SELECT t1.ID, a.FieldID, a.Field1, a.Field2, a.Field3, a.Field4
FROM Table1 as t1
INNER JOIN 
(SELECT t2.FieldID, t2.Field1, t2.Field2, t3.Field3, t3.Field4 FROM Table2 as t2
INNER JOIN Table3 as t3 ON t2.ID=t3.IDFrom2) as a
ON t1.IDFor2=a.FieldID
WHERE LEN(a.[Field1]) < 80 AND LEN(a.Field3) < 60
AND (CHARINDEX(LTRIM(RTRIM(REPLACE(t1.Field1,' ',''))),LTRIM(RTRIM(REPLACE(a.Field1,' ',''))))>0 OR CHARINDEX(LTRIM(RTRIM(REPLACE(a.Field1,' ',''))),LTRIM(RTRIM(REPLACE(t1.Field1,' ',''))))>0 OR t1.Field1 IS NULL)
AND (CHARINDEX(LTRIM(RTRIM(t1.Field2)),LTRIM(RTRIM(a.Field2)))>0 or CHARINDEX(LTRIM(RTRIM(a.Field2)),LTRIM(RTRIM(t1.Field2)))>0 OR t1.Field2 IS NULL)
AND (CHARINDEX(LTRIM(RTRIM(t1.Field3)),LTRIM(RTRIM(a.Field3)))>0 OR t1.Field3 IS NULL)
AND CHARINDEX(LTRIM(RTRIM(t1.Field4)),LTRIM(RTRIM(a.Field4)))>0

子查询

SELECT t2.FieldID, t2.Field1, t2.Field2, t3.Field3, t3.Field4 FROM Table2 as t2
INNER JOIN Table3 as t3 ON t2.ID=t3.IDFrom2

返回一些记录(具有相同的t2.Field),当单独运行时,它们与Table1有关系,只是过滤t2.FieldID等于Table1中的特定IDFor2

但是当两个查询连接在一起并在各个字段上匹配时,我获得两倍的记录,因为它为每个t1.ID返回一些重复项。如何修改我的查询以便每个t1.ID只检索一条记录(TOP 1)?

P.S。不幸的是,我无法提供真实数据,因为它是保密的。

更新:

子查询

SELECT t2.FieldID, t2.Field1, t2.Field2, t3.Field3, t3.Field4 FROM Table2 as t2
INNER JOIN Table3 as t3 ON t2.ID=t3.IDFrom2

返回以下两个表:

Table2                                   Table3
_____________________________________     _________________
abc123    Company1   Industry1  def       def   300   0.67
abc123    Company1   Industry1  fgh       fgh   500   0.81
abc123    Company1   Industry1  hjk       hjk   80    0.0045
abc123    Company2   Industry2  lmn       lmn   250   0.003
abc123    NULL       NULL       vck       vck   500   0.81


Table1
______________________________________________________
10001   abc123  1   Comp       Industry1   300   0.67
10002   abc123  2   NULL       NULL        500   0.81
10003   abc123  3   NULL       NULL        80    0.0045
10004   abc123  4   Company2   Industr     250   0.003
10005   abc123  5   NULL       NULL        500   0.81

我需要在关键字上组合Table2和Table3数据,这些数据是def,fgh等......

然后我需要将Table1与合并的Table2和Table3相匹配,然后对#34; rich&#34;进行排序。表1从表2和表3中提取的数据。我想得到类似的结果:

10001   abc123    Company1       Industry1   300   0.67
10002   abc123    Company1       Industry1   500   0.81
10003   abc123    Company1       Industry1   80    0.0045
10004   abc123    Company2       Industry2   250   0.003
10005   abc123    Company2       Industry2   500   0.81
相反,我得到了一种笛卡尔积:

10001   abc123  1   Company1    Industry1   300   0.67
10002   abc123  2   Company1    Industry1       500   0.81
10002   abc123  2   Company1    Industry2       500   0.81
10003   abc123  3   Company1    Industry1       80    0.0045
10004   abc123  4   Company2    Industry2       250   0.003
10005   abc123  5   Company2    Industry2       500   0.81
10005   abc123  5   Company2    Industry1       500   0.81

更新2:

我使用了Ionic的方法并且它起作用了。我修改了我的查询以使用row_number和partition:

SELECT * FROM
(SELECT t1.ID, a.FieldID, a.Field1, a.Field2, a.Field3, a.Field4
FROM Table1 as t1
INNER JOIN 
(SELECT t2.FieldID, t2.Field1, t2.Field2, t3.Field3, t3.Field4 FROM Table2 as t2
INNER JOIN Table3 as t3 ON t2.ID=t3.IDFrom2) as a
ON t1.IDFor2=a.FieldID
WHERE LEN(a.[Field1]) < 80 AND LEN(a.Field3) < 60
AND (CHARINDEX(LTRIM(RTRIM(REPLACE(t1.Field1,' ',''))),LTRIM(RTRIM(REPLACE(a.Field1,' ',''))))>0 OR CHARINDEX(LTRIM(RTRIM(REPLACE(a.Field1,' ',''))),LTRIM(RTRIM(REPLACE(t1.Field1,' ',''))))>0 OR t1.Field1 IS NULL)
AND (CHARINDEX(LTRIM(RTRIM(t1.Field2)),LTRIM(RTRIM(a.Field2)))>0 or CHARINDEX(LTRIM(RTRIM(a.Field2)),LTRIM(RTRIM(t1.Field2)))>0 OR t1.Field2 IS NULL)
AND (CHARINDEX(LTRIM(RTRIM(t1.Field3)),LTRIM(RTRIM(a.Field3)))>0 OR t1.Field3 IS NULL)
AND CHARINDEX(LTRIM(RTRIM(t1.Field4)),LTRIM(RTRIM(a.Field4)))>0) as b
WHERE b.rn=1

2 个答案:

答案 0 :(得分:2)

您可以在子查询上运行它并为每个t1.ID运行它以检索第一个值。但另一方面,您可以尝试使用ROW_NUMBER()解决此问题。

这是一个小例子,假设您有两个表t1t2。您只想在t2中第一次出现。

SELECT *
FROM t1
INNER JOIN (
        SELECT t2.id, t2.name, t2.create_date, 
            ROW_NUMBER() OVER(PARTITION BY t2.id ORDER BY t2.create_date) as rn
        FROM t2
    ) as t2
    ON t1.id = t2.id
WHERE t2.rn = 1

在这种情况下,这将基于create_date(在您的情况下,您的逻辑位于句子&#34;第一次出现&#34;)和分区(组)基于{{1 }}

然后你加入它,只关注t2.id

的行

答案 1 :(得分:0)

您可以在CTE功能的帮助下完成。您可以在CTE中创建select语句,然后将CTE与主表连接以获得您喜欢的结果

    WITH A
    (
      SELECT t2.id, t2.name, t2.create_date, 
        ROW_NUMBER() OVER(PARTITION BY t2.id ORDER BY t2.create_date) as rn
    FROM t2
    )
   SELECT t1.ID, a.FieldID, a.Field1, a.Field2, a.Field3, a.Field4 FROM A
     INNER JOIN T1
     ON t1.id = t2.id
   WHERE A.RN = 1