Sql server 2008 SQL Server 2008 R2中长UNION语句中的类似WHERE子句

Sql server 2008 SQL Server 2008 R2中长UNION语句中的类似WHERE子句,sql-server-2008,tsql,sql-server-2008-r2,Sql Server 2008,Tsql,Sql Server 2008 R2,在存储过程中,我需要将长联合的结果插入临时表。 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 DISTINC

在存储过程中,我需要将长联合的结果插入临时表。 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条记录,但这似乎很不完善

有更好的方法吗

总结我的问题:


有没有办法从tabid中只选择一次不同的myId,并将其分配给一种数组/列表/集合,而不是另一个临时表,然后在WHERE子句中使用它,如果有办法的话,对于这样一个小的3-6 recs临时表来说,这真的很重要吗?

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

我的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 ...

我认为,对于小桌子来说,以下内容可能更好,但在某些生产过程中,将其保留为这样是一个可怕的想法:

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

我忽略了你的要求,不需要另一个临时表,因为我不相信它是有根据的。尝试看看此解决方案是否能为您提供更好的性能:

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
当然,如果在所有20个表中都对col1进行了索引,并且该索引包括col2和col3,那么这将是最有效的

我建议使用视图的原因并不是因为我认为它会使代码运行得更快。只是您可以创建一个视图来为您生成此联合,使此代码更简单,并且使任何其他重复此单调联合的代码都更简单。这是一个方便的建议,不是为了性能——尽管我需要明确指出,使用视图并不会神奇地让事情变慢。有时我可以,但这是一个危险和不合逻辑的理由,以避免意见

最后,我会强烈考虑规范化。为什么这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,那么对SoeCeababID的索引或分区将是有用的。

听起来您应该考虑规范化而不是保存类型……背景:这些表Tab1…Tab20是我无法更改的现有系统的一部分。我正在做的是使用SSR添加报告。这就是为什么我希望在一个存储过程中执行所有操作,以避免重复太多查询。也就是说,我将如何使其正常化?非常感谢。你能创建,比如说,一个视图吗?我的视图问题,一般来说,我认为我可能错了,它们比存储过程慢。特别是在这种情况下,这些tab1…tabn可能非常大,在100到1000之间,我只需要一些与作为参数传递的条件相匹配的参数。@Amarundo请停止对视图或临时表之类的解决方案打折,因为您对这些东西有预先设想的概念。它们的存在是有原因的。如果有人向你提供一个或另一个或两个的解决方案,请持开放的态度。测试一下。如果它表现更差,那么好吧,至少你给了它一个机会。现在我没有兴趣帮助你解决这个问题,因为你正在消除多种潜在的解决方案,因为你的想法而不是你所知道的。这对对话来说是相当令人窒息的。DISTINCT出现在第一个SELECT上,而不是WHERE子句中的SELECT上。它确实节省了您一点打字时间。优化器应该将此查询和原始查询合并为同一个表单。不是真的,您的IN不正确,仍然需要在SELECT myId FROM TabIds_CTE中…我将查看该链接不幸的是,我无法规范化并创建一个大表。这些表是由一个产品创建的,该产品创建了一组新的表。我在这里所指的表只是每个表中的一个,我们称之为在系统中创建的新项目。我不能改变这一点。你的代码教会了我很多东西。我会研究的。再次感谢。