【发布时间】:2014-06-02 07:44:55
【问题描述】:
我有一个查询几乎适用于我的所有数据场景......除了一个。我有一个主表、一个详细表(包含一对多行项目)和许多连接到详细表的描述表(代码描述等)。我需要将所有详细记录连接成一个字符串值,以便每个主记录都有一条记录。所以如果主记录有3个细节,所有的值都需要连接成一个记录来代表主记录。
当主记录有多个详细记录但详细记录与描述表 1 到 1 不匹配时,我的问题就出现了。例如,在我的场景中,主记录有 3 个详细记录,其中只有一个详细记录有描述记录。所以从 1 到 3 到 1,Master 到 Detail 到 Description。这导致了一个问题。尝试连接记录时,代码不起作用,因为从 Detail 到 Description 连接创建的 NULL 值。我似乎可以让它工作的唯一方法是做一个 Distinct 子查询,然后在外面做我的连接逻辑。我觉得必须有更好的方法,或者我只是错过了一些东西。我在下面提供了示例代码来显示我的问题。有 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
【问题讨论】:
-
@DavidStratton 他不是在问如何连接字符串,而是如果有人知道一种更好的方法来删除他自己的空连接(第三次选择)
标签: sql sql-server sql-server-2008 concatenation