【问题标题】:Flag items not having the specified combination in a column标记列中没有指定组合的项目
【发布时间】:2021-10-14 05:56:43
【问题描述】:

我需要标记没有指定 DC 和存储位置组合的 ID#。例如:

每个 DC 的文章必须具有以下组合:

DC Storage Location
DC01 ABC, BCA, DCA
DC02 ABC, BCA
DC03 ABC, DCA

我想要的结果如下,因为我想显示缺少存储位置。

ID# DC# Storage Location Flag
1 DC02 ABC Good
1 DC02 BCA Good
2 DC01 ABC Bad
2 DC01 BCA Bad

错误条目是因为缺少“DCA”条目。到目前为止,我有以下内容,但是我无法弄清楚如何计算每个 ID 的匹配数(即 DC01 必须为 3,以便标志为 Good else Bad)。一旦找到标志,我唯一能想到的就是做一个联合(每个组合一个选择语句) - 有没有更优化的方法来做到这一点?

select
ID,
DC,
Storage_Location

FROM table
where 
DC = 'DC01' AND Storage_location in ('ABC', 'BCA', 'DCA')
group by ID, DC, Storage_location

表格包含多个ID,每个ID有不同的组合:

ID# DC# Storage Location
1 DC02 ABC
1 DC02 BCA
2 DC01 ABC
2 DC01 BCA
3 DC03 ABC
3 DC03 DCA

【问题讨论】:

  • 我不完全明白你的桌子是什么样子的。您正在使用 ID 显示所需的结果。能不能也显示一下原始表格数据,让我看看你是从哪里来的?
  • @ThorstenKettner 感谢您的回复,我已附上原始表格和一些示例数据
  • 用您使用的数据库标记您的问题。
  • 表格中是否有所需的位置组合?另外,SQL Server 的版本是多少?

标签: sql sql-server sql-server-2012 ssms


【解决方案1】:

您可以使用STRING_AGG查看数据是否完整。例如:

select
  id, dc, location,
  case when
  (
     select t.dc + ':' + string_agg(t2.location, ',') within group (order by t2.location)
     from mytable t2
     where t2.id = t.id and t2.dc = t.dc
  ) in ('DC01:ABC,BCA,DCA', 'DC02:ABC,BCA', 'DC03:ABC,DCA') then
    'GOOD'
  else
    'BAD'
  end as status
from mytable t
order by id, dc, location;

子查询是必要的,因为 SQL Server 中还没有 STRING_AGG 的解析版本。

【讨论】:

  • 谢谢,但是当我尝试时,我得到一个“函数 'string_agg' 可能没有 WITHIN GROUP 子句。”错误信息。我认为可能是子查询中的一些语法问题(在 ('DC01:ABC,BCA,DCA' ...)
  • 不,这不是子查询的问题。我已将我的查询放在 forpas 的演示中(仅修改了列名),它可以正常工作。请参阅dbfiddle.uk/…。我们的两个查询都在工作,并且使用了相同的技术。 WITHIN GROUP for STRING_AGG 在文档 (docs.microsoft.com/de-de/sql/t-sql/functions/…) 中也有提及。您使用的是哪个 SQL Server 版本?
  • 你会得到带有select @@version;的版本。
  • Microsoft SQL Server 2012 (SP4) (KB4018073) - 11.0.7001.0 (X64) 2017 年 8 月 15 日 10:23:29 版权所有 (c) Microsoft Corporation Enterprise Edition:基于内核的许可(64 位) ) 在 Windows NT 6.3 (Build 9600: )
  • 这解释了它。 SQL Server 2012 是一个非常旧的版本。它没有STRING_AGG。也许是升级的好时机。否则,您可以在 Internet 上查找如何在 SQL Server 2012 中模拟 STRING_AGG
【解决方案2】:

使用返回所有DCs 及其所需StorageLocations 的CTE 并加入表。
还在表中聚合并使用 STRING_AGG()(需要 SQL Server 2017 版)在逗号分隔列表中收集每个 DC 的实际 StorageLocations 并加入此查询:

WITH cte(DC, StorageLocation) AS (
  SELECT 'DC01', 'ABC,BCA,DCA' UNION ALL
  SELECT 'DC02', 'ABC,BCA' UNION ALL
  SELECT 'DC03', 'ABC,DCA'
)
SELECT t.*, CASE WHEN s.DC IS NULL THEN 'Bad' ELSE 'Good' END Flag 
FROM tablename t INNER JOIN cte c
ON c.DC = t.DC
LEFT JOIN (
  SELECT DC, STRING_AGG(StorageLocation, ',') WITHIN GROUP (ORDER BY StorageLocation) StorageLocation 
  FROM tablename
  GROUP BY DC
) s ON s.DC = c.DC AND s.StorageLocation = c.StorageLocation
ORDER BY t.ID, t.DC, t.StorageLocation;

请参阅demo

【讨论】:

  • 谢谢@forpas,但不幸的是,这段代码需要在另一个无法处理 CTE 的程序中提取。有没有其他方法可以在不创建 CTE 的情况下做到这一点?
  • 我之前标记为 ms-sql 但我的实际上是 mssq V18.4。为混乱道歉。这个版本好像不支持String_agg
猜你喜欢
  • 1970-01-01
  • 2011-09-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多