我有一个表,其中第一列包含一个 ID,该 ID 最多可以有 30 个不同的代码和与其关联的日期。
身份证 | 代码_1 | 代码_1_日期 | 代码_2 | 代码_2_日期 | 代码_3 | 代码_3_日期
这是我能想到的唯一方法,这似乎效率不高,而且也无法捕获日期:
SELECT ID, CODE_1, CODE_2, CODE_3
FROM CDHISTTBL
WHERE (ID = 'J12999' AND CODE_1 = 'AB99') or (ID = 'J12999' AND CODE_2 = 'AB99') or (ID = 'J12999' AND CODE_3 = 'AB99')
这就是我希望代码执行的方式:
SELECT ID, CODE, CODE_DATE
FROM CDHISTTBL
WHERE ID = 'J12999' AND CODE = 'AB99'
有没有一种方法可以执行此查询以简单地返回 ID、Code 和相应的日期值,而无需专门检查每个 ID+Code 组合?
你可以试试这个。打字更少,但本质上是一样的:
它也不会告诉您匹配代码的日期。
您确实想要一个如下所示的新表(语法可能有点不对)
从这里您可以找到您需要的东西。
在为您创建代码的代码的帮助下,您可以以简单的方式创建视图并获取数据。
示例数据(最多“4”;不想为“30”值执行此操作):
您感兴趣的值(ID = J12999 和
CODE_X
= 'AB99')位于CODE_1
日期等于 2022 年 1 月 15 日)CODE_4
日期等于 2023 年 1 月 28 日)为您编写代码的代码(在最后一行,您将使用
30
而不是4
因为您的表有 30 个代码):现在,复制/粘贴该输出并在创建视图时使用它(添加第一行并删除尾随
union all
):就是这样; 其余的都是微不足道的:
不过,考虑一下 @LoztInSpace 所说的并重新设计该表。它不应该是这样的。
更新之前的答案:如果您无法规范化表结构,您可以使用 vew 或 CTE 对其进行旋转:
要
SELECT
在许多地方使用 CTE 中的 ,请将其创建为视图,这样您就不必将其包含在需要此查找的每个查询中。我添加的列
CodeFoundInSlot
是可选的,如果代码的位置对您的查询并不重要,请将其删除。其性能可能比其他一些答案更差(尽管不比 30 个单独的选择差),因此请验证该解决方案在您的数据大小/模式上的性能是否可接受。
之前的回答:
正如 LoztInSpace 已经说过的,理想情况下,您将重新设计以标准化您的数据,从而使此类查询变得更加容易。
使用现有的结构,您可以执行以下操作:
如果没有找到任何内容,这将返回日期中包含 NULL 的行,您可以使用 CTE 或通过重复大型 CASE 子句来删除它:
远非理想,但它会起作用。同样,如果您有能力的话,重新排列数据结构将是更好的选择。
比 UNION ALL 更紧凑,无需动态生成 SQL,即可将单行转换为三行,因此每行只能专用于其中一个列对。
但是,如果您的每个 ID 值都有大量不同的 CODE 值,则此方法的效果不佳,因为后者无法编制索引。您仍然可以索引 ID,这可能就足够了。
有几个人提供了几种进行这种转换的方法。我希望每个问题所涉及的复杂性都表明 RDBMS 中的非规范化数据是多么不受欢迎。您绝对最好的解决方案是通过适当的标准化重新设计表格。首先,请确保您永远不会在任何数据库设计中使用像这样的重复列组。