0

在一个存储过程中,我需要将INSERT一个 long 的结果UNION放入一个临时表中。该WHERE子句对于所有表都是相同的,位于SELECT DISTINCT.

为了可读性而简化,它是这样的:

INSERT INTO #MyTemp
  SELECT col1, col2, col3 FROM tab1 WHERE col1 in (SELECT DISTINCT myId FROM TabIds) UNION
  SELECT col1, col2, col3 FROM tab2 WHERE col1 in (SELECT DISTINCT myId FROM TabIds) UNION
  SELECT col1, col2, col3 FROM tab3 WHERE col1 in (SELECT DISTINCT myId FROM TabIds) UNION
  .
  .
  .
  SELECT col1, col2, col3 FROM tab20 WHERE col1 in (SELECT DISTINCT myId FROM TabIds) 

虽然TabIds是一个小型临时表,通常有 3-6 条记录,但这似乎非常无用。

有一个更好的方法吗?

总结我的问题:

有没有一种方法我可以SELECT DISTINCT myId FROM TabIds只做一次并将其分配给一种数组/列表/集合(而不是另一个临时表),然后在WHERE子句中使用它,如果有办法,对于这样的小(3-6 记录)临时表?

4

4 回答 4

2

从概念上讲,您正在做的事情对于一次性和数据加载都很好。不过,我希望这不是生产代码中更大模式的一部分。

于 2013-03-04T21:25:38.410 回答
2

您正在寻找的是一个公用表表达式。

我的 T-SQL 有点生疏,但使用 CTE,您的查询将类似于:

WITH TabIds_CTE AS (SELECT DISTINCT myId FROM TabIds)
INSERT INTO #MyTemp
SELECT col1, col2, col3 FROM tab1 WHERE col1 IN (SELECT * FROM TabIds_CTE)
UNION ALL ...
于 2013-03-04T21:33:10.543 回答
2

我忽略了您的要求(“不要到另一个临时表”),因为我不相信它是有根据的。试试看这个解决方案是否能给你更好的性能:

SELECT i = myId
  INTO #x 
  FROM dbo.TabIds -- please always use schema prefix
  GROUP BY myId;

CREATE UNIQUE CLUSTERED INDEX x ON #x(i);

INSERT INTO #MyTemp(col1, col2, col3)
SELECT col1, col2, col3
FROM
(
  SELECT col1, col2, col3 FROM dbo.tab1 WHERE EXISTS -- likely better than IN
    (SELECT 1 FROM #x WHERE i = tab1.col1)
  UNION ALL 
  SELECT col1, col2, col3 FROM dbo.tab2 WHERE EXISTS 
    (SELECT 1 FROM #x WHERE i = tab2.col1)
  UNION ALL

  ...

  UNION ALL
  SELECT col1, col2, col3 FROM dbo.tab20 WHERE EXISTS 
    (SELECT 1 FROM #x WHERE i = tab20.col1)
) AS x
GROUP BY col1, col2, col3; -- likely more efficient than `UNION` to remove dupes

当然,如果col1在所有 20 个表中都建立了索引,并且该索引包括col2and ,这将最有效col3

我建议一个视图的原因并不是因为我认为它会使这段代码运行得更快。只是你可以创建一个视图来UNION为你生成这个,使这个代码更简单(以及任何其他重复这个单调的代码UNION)。这是为了方便而不是性能的建议——尽管我需要明确一点,使用视图不会神奇地让事情变慢。有时我可以,但这是一个危险且不合逻辑的回避观点的理由。

最后,我强烈考虑标准化。为什么这 20 张不同的桌子放在首位,而它们都可以放在一张桌子上?

CREATE TABLE dbo.Normal
(
  SourceTableID INT,
  col1 <data type>,
  col2 <data type>,
  col3 <data type>
);

-- indexes / constraints

INSERT dbo.Normal
SELECT 1, col1, col2, col3 FROM dbo.tab1
UNION ALL
SELECT 2, col1, col2, col3 FROM dbo.tab2
UNION ALL

...

UNION ALL
SELECT 20, col1, col2, col3 FROM dbo.tab20;

现在您的所有查询都可以简单地引用这个新表。如果您通常只寻找其中一个来源(例如tab5),那么索引或分区SourceTableID将很有用。

于 2013-03-06T14:21:25.287 回答
1

我认为以下对于小桌子可能会更好,但仍然 - 在某些生产过程中保持这样的想法是可怕的:)

INSERT INTO #MyTemp (col1,col2,col3)
select distinct
    x.col1,x.col2,x.col3 
from (
  SELECT col1, col2, col3 FROM tab1 union all
  SELECT col1, col2, col3 FROM tab2 union all 
  SELECT col1, col2, col3 FROM tab3 union all 
  -- ...
  SELECT col1, col2, col3 FROM tab20
) x
join (
    SELECT DISTINCT myId FROM TabIds
) y
on x.col1=y.myid
于 2013-03-05T16:32:22.067 回答