【问题标题】:How to exclude duplicate values / NULL values SQL如何排除重复值/空值 SQL
【发布时间】:2021-05-06 08:25:10
【问题描述】:

我希望您的某个人能够帮助我,因为我陷入了(愚蠢的)条件逻辑。 我正在加入 2 个临时表。 目标是始终在一行中查看一个收货人 (Consignee Ref) 的作业、跟踪编号等(所有操作)。换句话说,显示每个收货人参考的所有操作/数据。
我得到的问题是重复值。问题是 Original Job (620X) 字段可以分配 Tracking_1,但它也可以是 null。此外,Second Job (629X) 字段可以具有但不需要指定 Tracking 编号/值。对于一个 Consignee RefTracking_1Tracking 也可能为 NULL。 当我排除 Tracking_1TrackingNULL 的作业时,我将丢失根本没有跟踪编号的作业。所以我使用了下面的代码,但是我得到了重复。

SELECT * FROM #Temp t1
INNER JOIN #Temp2 t2 on t1.[Consignee Ref] = t2.[Consignee Ref]
WHERE t1.[Tracking_1] is not null
ORDER BY [Original Job (620X)] asc

我怎样才能摆脱不必要的重复(红色标记的示例)? 同时不要放弃那些没有跟踪号的工作?

我希望这是有道理的。 非常感谢您的任何建议!

这是完整的代码:

IF OBJECT_ID('tempdb..#Temp') IS NOT NULL
    DROP TABLE #Temp;

SELECT distinct
cne.[Consignee Ref], 
s.[Trial AWB] as [Original Job (620X)],
rl.[CarrierReference] as [Tracking_1],
CAST(st.[Sched Collection date] as date) AS [Collection Date],
CAST(st.[Act Del Date] as date) AS [Delivery Date],
s.[Clientaccountcode] as [Account Code]

into #Temp
FROM MKN_Reporting.dbo.shipment AS s WITH (NOLOCK)
LEFT JOIN MKN_Reporting.dbo.[Lookup Month By JN Tb] AS b WITH (NOLOCK) ON s.[id] = b.[JobId]
LEFT JOIN MKN_Reporting.dbo.[Lookup Branch currency Tb] AS c WITH (NOLOCK) ON b.BranchPrefix = c.[Branch Prefix] 
LEFT JOIN MKN_Reporting.dbo.[Lookup Client group Tb] AS g WITH (NOLOCK) ON s.[Clientaccountcode] = g.[Customer A/c]
LEFT JOIN MKN_Reporting.dbo.[Chargeto] AS cg WITH (NOLOCK) ON s.[id] = cg.[jobid]
LEFT JOIN MKN_Reporting.dbo.[Shipper] AS sh WITH (NOLOCK) ON s.[id] = sh.[jobid]
LEFT JOIN MKN_Reporting.dbo.[Cnee] AS cne WITH (NOLOCK) ON s.[id] = cne.[jobid]
LEFT JOIN MKN_Reporting.dbo.[Lookup Country & Region Tb] AS r WITH (NOLOCK) ON sh.[Shipper Country code] = r.[Country Code]
LEFT JOIN MKN_Reporting.dbo.[Lookup Country & Region Tb] AS reg WITH (NOLOCK) ON cne.[Consignee Country code] = reg.[Country Code]
INNER JOIN MKN_Reporting.dbo.[Status] st ON COALESCE(s.ParentId, s.id) = st.Jobid
LEFT JOIN [CARRIERS_CHARGES] AS cc ON s.id = cc.JobId   
LEFT JOIN [RouteLegs] as rl on cc.RouteLegId = rl.id

WHERE [Clientaccountcode] in ('US429', 'MI1091')
--AND rl.[CarrierReference] is not null

-------------------------------------------
IF OBJECT_ID('tempdb..#Temp2') IS NOT NULL
    DROP TABLE #Temp2;

SELECT distinct
cne.[Consignee Ref], 
s.[Study Number] as [Study_],
s.[Site Number] as [Site No_],
s.[Trial AWB] as [Second (629X)],
rl.[CarrierReference] as [Tracking],
CAST(st.[Sched Collection date] as date) AS [Collection Date],
CAST(st.[Act Del Date] as date) AS [Delivery Date],
s.[Clientaccountcode] as [Account Code]

into #Temp2
FROM MKN_Reporting.dbo.shipment AS s WITH (NOLOCK)
LEFT JOIN MKN_Reporting.dbo.[Lookup Month By JN Tb] AS b WITH (NOLOCK) ON s.[id] = b.[JobId]
LEFT JOIN MKN_Reporting.dbo.[Lookup Branch currency Tb] AS c WITH (NOLOCK) ON b.BranchPrefix = c.[Branch Prefix] 
LEFT JOIN MKN_Reporting.dbo.[Lookup Client group Tb] AS g WITH (NOLOCK) ON s.[Clientaccountcode] = g.[Customer A/c]
LEFT JOIN MKN_Reporting.dbo.[Chargeto] AS cg WITH (NOLOCK) ON s.[id] = cg.[jobid]
LEFT JOIN MKN_Reporting.dbo.[Shipper] AS sh WITH (NOLOCK) ON s.[id] = sh.[jobid]
LEFT JOIN MKN_Reporting.dbo.[Cnee] AS cne WITH (NOLOCK) ON s.[id] = cne.[jobid]
LEFT JOIN MKN_Reporting.dbo.[Lookup Country & Region Tb] AS r WITH (NOLOCK) ON sh.[Shipper Country code] = r.[Country Code]
LEFT JOIN MKN_Reporting.dbo.[Lookup Country & Region Tb] AS reg WITH (NOLOCK) ON cne.[Consignee Country code] = reg.[Country Code]
INNER JOIN MKN_Reporting.dbo.[Status] st ON COALESCE(s.ParentId, s.id) = st.Jobid
LEFT JOIN [CARRIERS_CHARGES] AS cc ON s.id = cc.JobId   
left JOIN [RouteLegs] as rl on cc.RouteLegId = rl.id    
WHERE [Clientaccountcode] in ('US1598')
--AND rl.[CarrierReference] is not null

---------------------------------------------
SELECT * FROM #Temp t1
INNER JOIN #Temp2 t2 on t1.[Consignee Ref] = t2.[Consignee Ref]
WHERE t1.[Tracking_1] is not null
ORDER BY [Original Job (620X)] asc

【问题讨论】:

  • 使用的查询语法看起来像 SQL Server (MS SQL)-relative,而不是 MySQL-relative。检查您的 DBMS,如果需要,重新标记。
  • 提供样本。为两个表创建表(可能会跳过任务的多余列),插入一些样本数据(每个表 5-10 行就足够了),该数据的期望结果,详细说明。

标签: sql sql-server null duplicates conditional-statements


【解决方案1】:

我猜 OP 正在为 T2 寻找某种字段聚合。 使用 SQL Server 2017+,就像在 PostgreSQL 中一样,您现在可以使用 STRING_AGG(与 Oracle LISTAGG 的语法相同。“他们为什么不使用相同的关键字...”)。

STRING_AGG 将忽略来自 T2 的空值,如果不是 单独,则需要分组。您必须添加其他 T1 和 T2 必填字段(如果有),但请注意 T2 它可能意味着重复并且可能也需要聚合...

这是您提供的 TSQL 的示例:

SELECT t1.[Consignee Ref], t1.[Original Job (620X)], t1.[Tracking_1],
       STRING_AGG(t2.[Tracking],',') WITHIN GROUP (ORDER BY t2.[Tracking] ASC) Tracking_T2
  FROM #Temp t1
       INNER JOIN #Temp2 t2 on t1.[Consignee Ref] = t2.[Consignee Ref]
 WHERE t1.[Tracking_1] is not null
 GROUP BY t1.[Consignee Ref], t1.[Original Job (620X)], t1.[Tracking_1]
 ORDER BY t1.[Original Job (620X)] asc

编辑:对于以前的 SQL Server 版本(2017 年之前),您可以使用 XML 查询实现字符串聚合:

EDIT2:添加 EXISTS 子句以从初始查询中传达 INNER JOIN。

SELECT t1.[Consignee Ref], t1.[Original Job (620X)], t1.[Tracking_1],
       STUFF((SELECT ', ' + t2.[Tracking]
                         FROM #Temp2 t2 
                        WHERE t1.[Consignee Ref] = t2.[Consignee Ref]
                        ORDER BY t2.[Tracking]
                          FOR XML PATH('')), 1, 1, N'') Tracking_T2
  FROM #Temp t1
 WHERE t1.[Tracking_1] is not null
   AND EXISTS (SELECT DISTINCT 1 FROM #Temp2 t2 WHERE t2.[Consignee Ref] = t1.[Consignee Ref])
 GROUP BY t1.[Consignee Ref], t1.[Original Job (620X)], t1.[Tracking_1]
 ORDER BY t1.[Original Job (620X)] asc

【讨论】:

  • 很遗憾,SSMS 无法识别内置函数名称 STRING_AGG
  • STRING_AGG 仅从 MSSQL17 和相关的 SSMS 14.+ 和 SMO 15.+ 起受支持。我猜你在以前的 SQL Server 版本上。我将编辑答案以添加 FOR XML PATH 对应的方式。
  • 编辑完成,它应该适用于您的 SQL Server 版本。
  • @AdélaŠkrábalová 添加了一个 EXISTS 子句以仅保留具有至少一个相应 t2 记录的 t1 记录,因为您的初始查询仅过滤具有相应 #temp2 记录的 #temp1 记录。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-04-15
  • 2017-03-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-27
  • 2019-09-05
相关资源
最近更新 更多