SQL自连接是实现;查找“;?

SQL自连接是实现;查找“;?,sql,sas,Sql,Sas,我正在运行一个SQL查询,它24次自联接同一个表,以便根据24个不同的条件“查找”表的特定行,以便在计算中使用所有这些值。虽然性能非常好(表被索引了,连接条件也很严格),但我还是忍不住觉得这里有一种代码的味道 在SQL中有更好的查找方法吗 (很抱歉没有举一个例子;我希望我用了一种普遍的方式来表达这个问题) 编辑:仍在尝试示例: CREATE TABLE key ( pk1 int, pk2 int, pk3 int, PRIMARY KEY (pk1, pk2,

我正在运行一个SQL查询,它24次自联接同一个表,以便根据24个不同的条件“查找”表的特定行,以便在计算中使用所有这些值。虽然性能非常好(表被索引了,连接条件也很严格),但我还是忍不住觉得这里有一种代码的味道

在SQL中有更好的查找方法吗

(很抱歉没有举一个例子;我希望我用了一种普遍的方式来表达这个问题)

编辑:仍在尝试示例:

CREATE TABLE key (
    pk1 int,
    pk2 int,
    pk3 int,
    PRIMARY KEY (pk1, pk2, pk3)
);

CREATE TABLE values (
    pk1 int,
    pk2 int,
    pk3 int,
    pk4 int,
    pk5 int,
    value int,
    PRIMARY KEY (pk1, pk2, pk3, pk4, pk5)
 );

 SELECT k.pk1, k.pk2, k.pk3,
        v1.value + v2.value - v3.value * (v4.value / v5.value) + ... + v24.value as result
 FROM key k
     LEFT JOIN values v1
         on v1.pk1=k.pk1
         and v1.pk2=k.pk2
         and v1.pk3=k.pk3
         and v1.pk4=100
         and v1.pk5=200

     LEFT JOIN values v2
         on v2.pk1=k.pk1
         and v2.pk2=k.pk2
         and v2.pk3=k.pk3
         and v2.pk4=400
         and v2.pk5=800

     ...

     LEFT JOIN values v24
         on v24.pk1=k.pk1
         and v24.pk2=k.pk2
         and v24.pk3=k.pk3
         and v24.pk4=900
         and v24.pk5=700;

编辑2:之所以采用这种结构,是因为“值”表(从数学上讲)表示5个变量的函数,表中存储了各种参数的预计算返回值。

如果我了解您要查找的内容,则更易于使用:

SELECT field1, field2 from Table1 t
where exists (SELECT 1 from LookupTable l where l.fieldX=t.fieldX) 

如果我了解您想要的是什么,那么使用起来就更容易了:

SELECT field1, field2 from Table1 t
where exists (SELECT 1 from LookupTable l where l.fieldX=t.fieldX) 

我开始用一个完整的查找表示例来回答这个问题,但我意识到还有一个更大的潜在问题

看看这些参考资料

您正在使用的模式类型与关系数据库的概念背道而驰。尝试将表展平,这样就不会有键/值关系

如果您的等式是非规则聚合(是的,不要查找该聚合),例如v1.val+v2.val/v3.val,那么您希望在一个或多个(但少于24个)联接之后,将该等式中的每个变量都放在一个或多个表中的一行中

实体属性值模式存在性能差、维护困难以及非常非常难闻的问题


这并没有回答问题,所以还是这样吧。使用Icarus在评论中建议的视图,或者将整个内容烧掉,重新构建更规范的内容。

我已经开始用一个完整的查找表示例来回答这个问题,但意识到有一个更大的潜在问题

看看这些参考资料

您正在使用的模式类型与关系数据库的概念背道而驰。尝试将表展平,这样就不会有键/值关系

如果您的等式是非规则聚合(是的,不要查找该聚合),例如v1.val+v2.val/v3.val,那么您希望在一个或多个(但少于24个)联接之后,将该等式中的每个变量都放在一个或多个表中的一行中

实体属性值模式存在性能差、维护困难以及非常非常难闻的问题


这并没有回答问题,所以还是这样吧。使用Icarus在评论中建议的视图,或者将整个内容烧掉,重新构建更规范的内容。

首先,这根本不是自连接

自联接是指将表联接到自身

例如层次结构中的父子关系以及与其他人有关系的人(字面上是父、子)

您给出的在不同角色中使用表的情况并不少见

如果表中的不同值在某种基本性质上不相关,我会对设计产生问题,因为“一次真正的查找”是一种情况,其中一次使用类型代码存储各种实体查找,因此您可以获得账单地址、客户、发货地址,产品和各种各样的东西都在同一个查找表中

在数据仓库中,还可以在不同的角色中使用维度,特别是日期或时间维度

如果对用作数组的列(例如第一个\u子级、第二个子级、第三个\u子级)反复连接同一个查找表,则会产生一种气味,因为这通常违反了规范化

我唯一关心的是你在这里展示的内容:

在所有值的5维空间中,用于拾取三维空间的幻数。我假设它们本身是在某个表中定义的(pk4、pk5、description)

在这一点上,我会考虑把每一个变成一个视图,使之更可读。

在SQLServer(或DB2中,它具有相同的构造),我实际上会考虑使用在PK4和PK5上参数化的内联表值函数,这将有助于防止有人意外地加入不完整的连接标准,并结束一个ITVF而不是多个视图。
但所有这些都只是简单的清理——查询和表的设计在我看来非常合理。

首先,这根本不是自连接

自联接是指将表联接到自身

例如层次结构中的父子关系以及与其他人有关系的人(字面上是父、子)

您给出的在不同角色中使用表的情况并不少见

如果表中的不同值在某种基本性质上不相关,我会对设计产生问题,因为“一次真正的查找”是一种情况,其中一次使用类型代码存储各种实体查找,因此您可以获得账单地址、客户、发货地址,产品和各种各样的东西都在同一个查找表中

在数据仓库中,还可以在不同的角色中使用维度,特别是日期或时间维度

如果对用作数组的列(例如第一个\u子级、第二个子级、第三个\u子级)反复连接同一个查找表,则会产生一种气味,因为这通常违反了规范化

我唯一关心的是你在这里展示的内容:

在所有值的5维空间中,用于拾取三维空间的幻数。我假设它们本身是在某个表中定义的(pk4、pk5、des)
EXPLAIN ANALYZE
WITH zzz AS (
        SELECT v.pk1 AS pk1
        , v.pk2 AS pk2
        , v.pk3 AS pk3
        , p.num AS num
        , v.value AS value
        FROM zparams p
        JOIN zvalues v ON v.pk4 = p.pk4 AND v.pk5=p.pk5
        )
 SELECT k.pk1, k.pk2, k.pk3,
        v1.value + v2.value - v3.value * (v4.value / v5.value) + v24.value as result
 FROM zkeys k
     LEFT JOIN zzz v1
         ON v1.pk1=k.pk1 AND v1.pk2=k.pk2 AND v1.pk3=k.pk3
         AND v1.num=1

     LEFT JOIN zzz v2
         ON v2.pk1=k.pk1 AND v2.pk2=k.pk2 AND v2.pk3=k.pk3
         AND v2.num=2

     LEFT JOIN zzz v3 ON v3.pk1=k.pk1 AND v3.pk2=k.pk2 AND v3.pk3=k.pk3
         AND v3.num=3

     LEFT JOIN zzz v4
         ON v4.pk1=k.pk1 AND v4.pk2=k.pk2 AND v4.pk3=k.pk3
         AND v4.num=4

     LEFT JOIN zzz v5
         ON v5.pk1=k.pk1 AND v5.pk2=k.pk2 AND v5.pk3=k.pk3
         AND v5.num=5

     LEFT JOIN zzz v24
         ON v24.pk1=k.pk1 AND v24.pk2=k.pk2 AND v24.pk3=k.pk3
         AND v24.num=24
        ;
data x;
  merge key 
        values(rename=value=value1 where=(pk4=100 and pk5=200))
        values(rename=value=value2 where=(pk4=400 and pk5=800))
        values(rename=value=value3 where=(pk4=900 and pk5=700))
        etc...
        ;
  by pk1 pk2 pk3;
  result = ...;
  keep pk: value: result;
run;
CREATE TABLE XX AS 
SELECT k.pk1, k.pk2, k.pk3, v1.pk4, v1.pk5, v1.value
     FROM key k
 LEFT JOIN values v1
     on v1.pk1=k.pk1
     and v1.pk2=k.pk2
     and v1.pk3=k.pk3
     and ( 
          (v1.pk4=100 and v1.pk5=200) or
          (v1.pk4=400 and v1.pk5=800) or
          (v1.pk4=700 and v1.pk5=900) 
         )


proc transpose data=xx out=trans;
  by pk1 pk2 pk3;
  var value;
run;

data result;
  set trans;
  result = ...;
run;