我的查询几乎适用于所有数据场景......除了一个。我有一个主表,一个详细信息表(包含一到多个行项),以及许多连接到详细信息表的描述表(代码描述等)。我需要将所有详细记录连接成一个字符串值,以便每个主记录有一个记录。因此,如果主记录有3个详细信息,则需要将所有值连接到一个记录中以表示主记录。
我的问题出现在主记录有多个详细记录但细节记录与描述表1到1不匹配时。例如,在我的方案中,主记录有3个详细记录,其中只有一个详细记录中有描述记录。所以1到3比1,Master to Detail to Description。这导致了一个问题。当尝试连接记录时,代码不起作用,因为从Detail to Description连接创建了NULL值。我似乎能够让它工作的唯一方法是做一个不同的子查询,然后在外面做我的连接逻辑。我觉得必须有一个更好的方法,或者我只是缺少一些东西。我在下面提供了示例代码来说明我的问题。有3个选择可以运行。第一个是连接中所有记录的平坦结果。第二个是我原来的逻辑显示缺陷。第三个是工作版本,我希望有人知道如何做得更好。我非常感谢您对此问题的任何帮助。
DECLARE @Notification table(
SystemID int NOT NULL,
NotificationID int
);
DECLARE @NotificationItems table(
SystemID int NOT NULL,
NotificationID VARCHAR(100),
LineItem VARCHAR(100)
);
DECLARE @NotificationCauses table(
SystemID int NOT NULL,
NotificationID VARCHAR(100),
LineItem VARCHAR(100),
TestValue VARCHAR(100)
);
INSERT INTO @Notification
SELECT 40,1 UNION
SELECT 40,2 UNION
SELECT 40,3 UNION
SELECT 40,4
INSERT INTO @NotificationItems
SELECT 40,1,1 UNION
SELECT 40,1,2 UNION
SELECT 40,1,3 UNION
SELECT 40,2,1 UNION
SELECT 40,2,2 UNION
SELECT 40,3,1
INSERT INTO @NotificationCauses
SELECT 40,1,1,'Code_A' UNION
SELECT 40,2,1,'Code_B' UNION
SELECT 40,2,2,'Code_C' UNION
SELECT 40,3,1,'Code_D'
--SELECT *
--FROM @Notification
--SELECT *
--FROM @NotificationItems
SELECT *
FROM @Notification AS n
LEFT OUTER JOIN @NotificationItems AS ni
ON n.NotificationID = ni.NotificationID
AND n.SystemID = ni.SystemID
LEFT OUTER JOIN @NotificationCauses AS nc
ON ni.NotificationID = nc.NotificationID
AND ni.SystemID = nc.SystemID
AND ni.LineItem = nc.LineItem
SELECT DISTINCT n.SystemID, n.NotificationID
,SUBSTRING(
(
SELECT DISTINCT
CASE WHEN LTRIM(RTRIM(ni1.LineItem)) <> ISNULL('','') THEN ', '+ni1.LineItem ELSE '' END AS [text()]
FROM @NotificationItems AS ni1
WHERE ni1.SystemID = ni.SystemID AND ni1.NotificationID = ni.NotificationID --AND a1.LineItem = a.LineItem
ORDER BY 1
FOR XML PATH ('')
), 2, 1000) AS [LineItem]
,SUBSTRING(
(
SELECT DISTINCT
CASE WHEN LTRIM(RTRIM(nc1.TestValue)) <> ISNULL('','') THEN ', '+nc1.TestValue ELSE '' END AS [text()]
FROM @NotificationCauses AS nc1
WHERE nc1.SystemID = nc.SystemID AND nc1.NotificationID = nc.NotificationID --AND nc1.LineItem = nc.LineItem
ORDER BY 1
FOR XML PATH ('')
), 2, 1000) AS [TestValues]
FROM @Notification AS n
LEFT OUTER JOIN @NotificationItems AS ni
ON n.SystemID = ni.SystemID
AND n.NotificationID = ni.NotificationID
LEFT OUTER JOIN @NotificationCauses AS nc
ON ni.SystemID = nc.SystemID
AND ni.NotificationID = nc.NotificationID
AND ni.LineItem = nc.LineItem
SELECT DISTINCT SystemID, NotificationID
,SUBSTRING(
(
SELECT DISTINCT
CASE WHEN LTRIM(RTRIM(a1.LineItem)) <> ISNULL('','') THEN ', '+a1.LineItem ELSE '' END AS [text()]
FROM @NotificationItems AS a1
WHERE a1.SystemID = a.SystemID AND a1.NotificationID = a.NotificationID --AND a1.LineItem = a.LineItem
ORDER BY 1
FOR XML PATH ('')
), 2, 1000) AS [LineItem]
,SUBSTRING(
(
SELECT DISTINCT
CASE WHEN LTRIM(RTRIM(a1.TestValue)) <> ISNULL('','') THEN ', '+a1.TestValue ELSE '' END AS [text()]
FROM @NotificationCauses AS a1
WHERE a1.SystemID = a.SystemID AND a1.NotificationID = a.NotificationID --AND a1.LineItem = a.LineItem
ORDER BY 1
FOR XML PATH ('')
), 2, 1000) AS [TestValues]
FROM
(
SELECT DISTINCT n.NotificationID, n.SystemID, ni.LineItem, nc.TestValue
FROM @Notification AS n
LEFT OUTER JOIN @NotificationItems AS ni
ON n.SystemID = ni.SystemID
AND n.NotificationID = ni.NotificationID
LEFT OUTER JOIN @NotificationCauses AS nc
ON ni.SystemID = nc.SystemID
AND ni.NotificationID = nc.NotificationID
AND ni.LineItem = nc.LineItem
) AS a
答案 0 :(得分:2)
我已经清除了查询,结果是
SELECT n.SystemID, n.NotificationID
, SUBSTRING((SELECT COALESCE(', ' + ni.LineItem, '') [text()]
FROM NotificationItems AS ni
WHERE ni.SystemID = n.SystemID
AND ni.NotificationID = n.NotificationID
ORDER BY 1
FOR XML PATH ('')
), 2, 1000) AS [LineItem]
, SUBSTRING((SELECT COALESCE(', ' + nc.TestValue, '') [text()]
FROM NotificationItems AS ni
INNER JOIN NotificationCauses nc
ON ni.SystemID = nc.SystemID
AND ni.NotificationID = nc.NotificationID
AND ni.LineItem = nc.LineItem
WHERE ni.SystemID = n.SystemID
AND ni.NotificationID = n.NotificationID
ORDER BY 1
FOR XML PATH ('')
), 2, 1000) AS [TestValues]
FROM Notification n
那些是&#34;气味&#34;成立:
ISNULL('', '')
,它实际上什么也没做,替换为空白字符串''
(更多内容)
主要选择的FROM
,当只有一个真正使用时,有三个表,未使用的两个被删除,需要更新FROM和WHERE条件子查询
子查询的DISTINCT
,再次没有做任何事情,被剥夺了
子查询中的CASE
在值之前添加逗号,如果修剪后的值不为空,那正是COALESCE(', ' + value, '')
所做的(如果需要修剪则重新添加它) )
其他所有内容都只是以我的方式格式化查询,并且如果按照自己的方式进行格式化(例如通过重构进行审核),则更容易阅读
Here是使用提供的数据清除查询的SQLFiddle演示