我有一个SQL Server查询,我想要左边连接到2个表。我需要它来返回第一个表中的所有行,只返回其他2个表中的匹配数据。我的第一个化身创造了某种十字产品,其所需行数超过10倍。所以我添加了一个rowcount函数并让它过滤所有rowcount值= 1.现在它返回正确的行数,但是其他2个表中的数据错误。
我有一些过滤规则(case语句)我应用于2个右表的内容,以确定返回的内容(如果有的话)。我认为这可能是问题的根源,但我不确定。我已尝试在select语句中使用过滤器代码,并在查询结束时使用where语句,甚至作为join on语句的一部分。我也尝试过使用cross和outer。一切都没有用。
我试图在不使用循环的情况下实现此目的。可能吗?请参阅下面的代码。此代码生成太多行。我不会重复第二次迭代,因为它在顶部添加了一个额外的选择,并且在底部添加了m = 1的过滤器以生成正确的行数。
这是我要加入的2个表格。请注意,第二个表只是更大表的一小部分。
感谢!!!
SELECT
GLENTRY.Fac + GLENTRY.Rundt + GLENTRY.Jrnllog AS UniqueID,
GLENTRY.Fac AS Fac,
(CASE WHEN
EntityTranslate2014.AcctEnd <> '' AND EntityTranslate2014.AcctEnd = SUBSTRING(GLENTRY.Acct,6,3)
THEN
EntityTranslate2014.Entity
ELSE
CASE WHEN
EntityTranslate2014.AcctEnd <> 0 AND EntityTranslate2014.Acct = GLENTRY.Acct
THEN
EntityTranslate2014.Entity
ELSE
CASE WHEN
EntityTranslate2014.SSDept <> 0 AND EntityTranslate2014.SSDept = SUBSTRING(GLENTRY.Acct,1,4)
THEN
EntityTranslate2014.Entity
ELSE
CASE WHEN
EntityTranslate2014.SSDept = 0
AND
EntityTranslate2014.AcctEnd = ''
AND
EntityTranslate2014.Acct = 0
THEN
EntityTranslate2014.Entity
ELSE
''
END
END
END
END)
AS NEWEntity,
(CASE WHEN AcctTranslate2014.Fac = GLENTRY.Fac OR AcctTranslate2014.Fac = '0'
THEN
AcctTranslate2014.NEWDept
ELSE
Null
END)
AS Department,
(CONVERT(DATETIME,GLENTRY.Period + '/01/' +
CASE WHEN
CONVERT(NVARCHAR(4),GLENTRY.Yearz) = ''
THEN
'2014'
ELSE
GLENTRY.Yearz
END)
AS YEARPER,
GLENTRY.Acct) AS SSAcct,
CONVERT(NVARCHAR(20),
CASE WHEN
AcctTranslate2014.Fac = GLENTRY.Fac OR AcctTranslate2014.Fac = '0'
THEN
AcctTranslate2014.NEWAcct
ELSE
Null
END)
AS NEWAccount,
GLENTRY.Rundt,
GLENTRY.Jrnlid,
GLENTRY.Amount,
GLENTRY.Dc,
GLENTRY.Ref,
GLENTRY.Refdt,
CONVERT(NVARCHAR(100),'Import of SS ' + CONVERT(VARCHAR(2),GLENTRY.Period) + '/' + CONVERT(VARCHAR(4),GLENTRY.Yearz) + ' GL activity') AS Descr,
GLENTRY.Invnr,
GLENTRY.Jrnllog,
ROW_NUMBER() OVER(PARTITION BY GLENTRY.Fac, GLENTRY.Yearz, GLENTRY.Period, GLENTRY.Pagez, GLENTRY.Acct, GLENTRY.Rundt, GLENTRY.Jrnlid,
GLENTRY.Amount, GLENTRY.Dc, GLENTRY.Ref, GLENTRY.Refdt, GLENTRY.Descr, GLENTRY.Invnr, GLENTRY.Origfac, GLENTRY.Jrnllog, GLENTRY.Seq
ORDER BY GLENTRY.Fac, GLENTRY.Yearz, GLENTRY.Period) AS m
FROM GLENTRY
LEFT OUTER JOIN
EntityTranslate2014 ON GLENTRY.Fac = EntityTranslate2014.Fac
LEFT OUTER JOIN
AcctTranslate2014 ON CONVERT(VARCHAR(8),GLENTRY.Acct) = AcctTranslate2014.SSAcct
WHERE GLENTRY.Yearz = 2014 AND GLENTRY.Period = 11
EntityTranslate2014 File
Fac Entity Descr AcctEnd SSDept Acct
1 51900 Entity1 0 0
2 50901 Entity2 0 0
3 10100 Entity3 0 0
3 10500 Entity4 4016 0
3 10500 Entity4 4020 0
3 10500 Entity4 4022 0
3 10500 Entity4 4024 0
3 10500 Entity4 4028 0
3 10500 Entity4 7016 0
4 30900 Entity5 0 0
5 10300 Entity6 0 0
6 11300 Entity7 0 0
7 11100 Entity8 0 0
7 11500 Entity9 4016 0
7 11500 Entity9 4020 0
7 11500 Entity9 4022 0
7 11500 Entity9 4024 0
7 11500 Entity9 4028 0
7 11500 Entity9 7016 0
9 32909 Entity10 0 0
10 12100 Entity11 0 0
11 32901 Entity12 0 0
12 53900 Entity13 0 0
13 10200 Entity14 0 0
14 32914 Entity15 0 0
15 32915 Entity16 0 0
16 11200 Entity17 0 0
17 32917 Entity18 0 0
18 32918 Entity19 0 0
19 32919 Entity20 0 0
20 32920 Entity21 0 0
21 13100 Entity22 0 0
22 52900 Entity23 0 0
89 99900 Entity24 0 0
123 12300 Entity25 0 0
124 12200 Entity26 0 0
133 13300 Entity27 0 0
201 11201 Entity28 0 0
202 11202 Entity29 0 0
402 25402 Entity30 0 0
403 25403 Entity31 0 0
549 25430 Entity32 0 0
549 25432 Entity33 7195 0
910 50910 Entity34 0 0
911 50911 Entity35 0 0
21 13500 Entity36 4016 0
21 13500 Entity36 4020 0
21 13500 Entity36 4022 0
21 13500 Entity36 4024 0
21 13500 Entity36 4028 0
21 13500 Entity36 7016 0
16 11202 Entity37 0 002 0
16 11201 Entity37 0 001 0
16 11200 Entity38 0 30918000
16 11200 Entity38 0 31918000
16 11200 Entity38 0 32110000
AcctTranslate2014
NewAcct SSAcct NewDEpt Fac
10111500 111200010 000 0
10111600 111200050 000 0
10111700 111550010 000 0
10113092 111050450 000 0
10115090 111050010 000 0
答案 0 :(得分:1)
...更新
您可以使用ROW_NUMBER
计算联接结果中的序列,并使用ORDER BY
对它们进行排序,以便您想要的行在该序列中排在第一位。
感谢您发布循环结构,我认为我能够通过一系列CTE(WITH别名为(...))来近似它的功能。我不确定我的所有表/字段名称是否正确,但这应该接近功能。我的一个主要猜测是&#34;第一个&#34;应该确定实体,您可能需要在CTE中的行号函数中调整顺序。
WITH ENTFIND AS (
SELECT
EntityTranslate2014.Fac,
EntityTranslate2014.Acct,
EntityTranslate2014.AcctEnd,
EntityTranslate2014.Entity,
EntityTranslate2014.SSDept,
EntityTranslate2014.Entity,
ROW_NUMBER() OVER (PARTITION BY Fac, Acct, AcctEnd ORDER BY Fac, Acct, AcctEnd, Entity) as E1Sort
FROM
EntityTranslate2014
),
E2 AS (
SELECT
*,
ROW_NUMBER() OVER (PARTITION BY Fac, Acct, AcctEnd ORDER BY Fac, Acct, AcctEnd, Entity) as E2Sort
FROM
ENTFIND
WHERE
AcctEnd <> 0
),
E3 AS (
SELECT
*,
ROW_NUMBER() OVER (PARTITION BY Fac, Acct, AcctEnd ORDER BY Fac, Acct, AcctEnd, Entity) as E3Sort
FROM
ENTFIND
WHERE
SSDept <> 0
),
E4 AS (
SELECT
*,
ROW_NUMBER() OVER (PARTITION BY Fac, Acct, AcctEnd ORDER BY Fac, Acct, AcctEnd, Entity) as E4Sort
FROM
ENTFIND
WHERE
Acct = 0
AND
AcctEnd = ''
AND
SSDept = 0
)
SELECT
GLENTRY.Fac + GLENTRY.Rundt + GLENTRY.Jrnllog AS UniqueID,
GLENTRY.Fac AS Fac,,
E1.Entity,
E2.Entity,
E3.Entity,
E4.Entity,
COALESCE(E1.Entity,E2.Entity,E3.Entity,E4.Entity) as 1stFoundEntity,
(CASE WHEN
EntityTranslate2014.AcctEnd <> '' AND EntityTranslate2014.AcctEnd = SUBSTRING(GLENTRY.Acct,6,3)
THEN
EntityTranslate2014.Entity
ELSE
CASE WHEN
EntityTranslate2014.AcctEnd <> 0 AND EntityTranslate2014.Acct = GLENTRY.Acct
THEN
EntityTranslate2014.Entity
ELSE
CASE WHEN
EntityTranslate2014.SSDept <> 0 AND EntityTranslate2014.SSDept = SUBSTRING(GLENTRY.Acct,1,4)
THEN
EntityTranslate2014.Entity
ELSE
CASE WHEN
EntityTranslate2014.SSDept = 0
AND
EntityTranslate2014.AcctEnd = ''
AND
EntityTranslate2014.Acct = 0
THEN
EntityTranslate2014.Entity
ELSE
''
END
END
END
END)
AS NEWEntity,
(CASE WHEN AcctTranslate2014.Fac = GLENTRY.Fac OR AcctTranslate2014.Fac = '0'
THEN
AcctTranslate2014.NEWDept
ELSE
Null
END)
AS Department,
(CONVERT(DATETIME,GLENTRY.Period + '/01/' +
CASE WHEN
CONVERT(NVARCHAR(4),GLENTRY.Yearz) = ''
THEN
'2014'
ELSE
GLENTRY.Yearz
END)
AS YEARPER,
GLENTRY.Acct) AS SSAcct,
CONVERT(NVARCHAR(20),
CASE WHEN
AcctTranslate2014.Fac = GLENTRY.Fac OR AcctTranslate2014.Fac = '0'
THEN
AcctTranslate2014.NEWAcct
ELSE
Null
END) AS NEWAccount,
GLENTRY.Rundt,
GLENTRY.Jrnlid,
GLENTRY.Amount,
GLENTRY.Dc,
GLENTRY.Ref,
GLENTRY.Refdt,
CONVERT(NVARCHAR(100),'Import of SS ' + CONVERT(VARCHAR(2),GLENTRY.Period) + '/' + CONVERT(VARCHAR(4),GLENTRY.Yearz) + ' GL activity') AS Descr,
GLENTRY.Invnr,
GLENTRY.Jrnllog,
ROW_NUMBER() OVER(PARTITION BY GLENTRY.Fac, GLENTRY.Yearz, GLENTRY.Period, GLENTRY.Pagez, GLENTRY.Acct, GLENTRY.Rundt, GLENTRY.Jrnlid,
GLENTRY.Amount, GLENTRY.Dc, GLENTRY.Ref, GLENTRY.Refdt, GLENTRY.Descr, GLENTRY.Invnr, GLENTRY.Origfac, GLENTRY.Jrnllog, GLENTRY.Seq
ORDER BY GLENTRY.Fac, GLENTRY.Yearz, GLENTRY.Period) AS m
FROM
GLENTRY
LEFT JOIN
ENTFIND E1 ON GLENTRY.Fac = E1.Fac
AND SUBSTRING(GLENTRY.Acct,6,3) = E1.AcctEnd
AND E1Sort = 1
LEFT JOIN
E2 ON GLENTRY.Fac = E2.Fac
AND GLENTRY.Acct = E2.Acct
AND E2.E2Sort = 1
LEFT JOIN
E3 ON GLENTRY.Fac = E3.Fac
AND SUBSTRING(GLENTRY.Acct,1,4) = E3.SSDept
AND E3.E3Sort = 1
LEFT JOIN
E4 ON GLENTRY.Fac = E4.Fac
AND E4.E4Sort = 1
LEFT OUTER JOIN
EntityTranslate2014 ON GLENTRY.Fac = EntityTranslate2014.Fac
LEFT OUTER JOIN
AcctTranslate2014 ON CONVERT(VARCHAR(8),GLENTRY.Acct) = AcctTranslate2014.SSAcct
WHERE
GLENTRY.Yearz = 2014 AND GLENTRY.Period = 11
答案 1 :(得分:1)
FROM GLENTRY
LEFT OUTER JOIN EntityTranslate2014
ON GLENTRY.Fac = EntityTranslate2014.Fac
LEFT OUTER JOIN AcctTranslate2014
ON CONVERT(VARCHAR(8), GLENTRY.Acct) = AcctTranslate2014.SSAcct
EntityTranslate2014
和AcctTranslate2014
之间没有定义关系。如果GLENTRY
中相应记录的任一表中有多个记录,则这两个表将有效地相互交叉连接。例如,如果单个GLENTRY
加入EntityTranslate2014
中的两个记录和AcctTranslate2014
中的两个记录,那么您将获得4个记录,每个记录对应一个可能的组合。这就是JOIN
的定义方式。
如果您知道这种情况正在发生并且您知道实际上没有任何关系,并且您只想要GLENTRY
EntityTranslate2014
中AcctTranslate2014
中的每条记录与第一条记录相匹配EntityTranslate2014
以及AcctTranslate2014
中与FROM GLENTRY
LEFT OUTER JOIN (
SELECT *,
ROW_NUMBER() OVER (PARTITION BY Fac ORDER BY <SomeField>) row_order
FROM EntityTranslate2014) ET2014
ON GLENTRY.Fac = ET2014.Fac
LEFT OUTER JOIN (
SELECT *,
ROW_NUMBER() OVER (PARTITION BY SSAcct ORDER BY <SomeField>) row_order
FROM AcctTranslate2014) AT2014
ON CONVERT(VARCHAR(8), GLENTRY.Acct) = AT2014.SSAcct
AND AT2014.row_order = ET2014.row_order
中的第二条记录匹配的第二条记录,依此类推,您可以做我所听到的称为“ZIP加入”的内容:
SELECT *
显然,不要使用NULL
;这只是一个例子。所以,这样做是为每个OUTER表分配一些顺序,并将它们相互匹配。因此,每个OUTER表中的每条记录只会出现一次。如果不匹配,则其他表中的记录将显示为GLENTRY
s。
另一个常见的替代方法是简单地返回每个OUTER表的第一条记录,这样您就可以保证只有一条{{1}}条记录,因为每个OUTER表只为每个键字段贡献一条或零条记录。
如果 不能用于您的目的,那么您可能需要使用两个查询,并且需要在您的应用程序中进行匹配。
答案 2 :(得分:1)
您可以使用相关子查询来&#34;循环&#34;通过一个表中的每一行将它与另一个表中的行进行比较而不实际编写循环逻辑(在SQL中应避免使用)。内部查询中的行将根据where谓词与外部查询中的每一行进行比较。如果在WHERE子句查询中返回多于1条记录,则相关子查询还允许您通过TOP 1过滤WHERE子句(如下面的代码所示)。这只是一个简单的例子,因为我没有时间完整地写出代码,但它可能会有所帮助。
SELECT Entity
FROM EntityTranslate2014 ent
WHERE ent.AcctEnd <> ''
AND AcctEnd = (SELECT TOP 1 SUBSTRING(glt.Acct,6,3)
FROM Glentry glt
WHERE glt.fac = ent.fac
AND glt.Year = 2014
AND glt.Period = 11
ORDER BY glt.Fac, glt.Yearz, glt.Period)
在此示例中,EntityTranslate2014表中的每条记录都会根据Glentry.Fac = EntityTraslate2014.fac的谓词与内部查询的结果进行比较。希望有所帮助。
有关相关子查询的更多信息,请查看以下链接。
https://technet.microsoft.com/en-us/library/ms187638%28v=sql.105%29.aspx
答案 3 :(得分:1)
我想在我试图让我的查询工作时感谢大家的想法。我最终得到了以下解决方案。注意,为了简洁起见,我只包括用于确定实体字段的代码。它不漂亮,我确信它是最佳的,但它确实有效。
再次感谢您的帮助!!
CASE WHEN
(SELECT
BET.Entity
FROM
BET
WHERE
GL.Fac = BET.Fac
AND
BET.AcctEnd <> ''
AND
BET.AcctEnd = SUBSTRING(CONVERT(NVARCHAR(8),GL.Acct),6,3))
IS NOT Null
THEN
(SELECT
BET.Entity
FROM
SOSViews.dbo.BI360EntityTranslate2014 BET
WHERE
GL.Fac = BET.Fac AND BET.AcctEnd <> ''
AND
BET.AcctEnd = SUBSTRING(CONVERT(NVARCHAR(8),GL.Acct),6,3))
ELSE
CASE WHEN
(SELECT
BET.Entity
FROM
SOSViews.dbo.BI360EntityTranslate2014 BET
WHERE
GL.Fac = BET.Fac
AND
BET.SOSDept <> 0
AND
BET.SOSDept = SUBSTRING(CONVERT(NVARCHAR(8),GL.Acct),1,4))
IS NOT Null
THEN
(SELECT
BET.Entity
FROM
BET
WHERE
GL.Fac = BET.Fac
AND
BET.SOSDept <> 0
AND
BET.SOSDept = SUBSTRING(CONVERT(NVARCHAR(8),GL.Acct),1,4))
ELSE
CASE WHEN
(SELECT
BET.Entity
FROM
BET
WHERE
GL.Fac = BET.Fac
AND
BET.SOSDept = 0 AND BET.AcctEnd = '' AND BET.Acct = 0)
IS NOT Null
THEN
(SELECT
BET.Entity
FROM
BET
WHERE
GL.Fac = BET.Fac
AND
BET.SOSDept = 0 AND BET.AcctEnd = '' AND BET.Acct = 0)
ELSE
'No Entity Translation'
END
END
END)
AS Entity,
答案 4 :(得分:0)
注意:虽然它可能无法直接应用于OP的问题,但有时如果连接中的行太多,则只需加入错误的列即可。这恰好发生在我身上......