5

我遇到了一个问题,我需要运行一个查询,该查询应该从主表中获取一些行,并且如果主表的键存在于子表中(一对多的关系),则有一个指示符。

查询可能是这样的:

select a.index, (select count(1) from second_table b where a.index = b.index) 
from first_table a;

这样我会得到我想要的结果(0 = second_table 中没有依赖记录,否则有),但是我正在为从数据库中获得的每条记录运行一个子查询。我需要为至少三个相似的表获取这样的指标,并且主查询已经是至少两个表之间的一些内部连接......

我的问题是是否有一些真正有效的方法来处理这个问题。我曾想过在“first_table”的新列中记录,但 dbadmin 不允许触发器,并且通过代码跟踪它太冒险了。

解决这个问题的好方法是什么?

此查询的应用将用于两件事:

  1. 指示 first_table 中的给定行在 second_table 中至少存在一行。它是在一个列表中表明它。如果第二个表中不存在任何行,我不会打开这个指示器。
  2. 搜索 first_table 中所有在 second_table 中至少有一行的行,或者在第二个表中没有行的所有行。

我刚刚发现的另一个选项:

select a.index, b.index 
from first_table a 
left join (select distinct(index) as index from second_table) b on a.index = b.index

这样,如果 b.index 不存在,我将得到它的 null (最终可以调整显示,我担心这里的查询性能)。

这个问题的最终目标是为这种情况找到合适的设计方法。这种情况经常发生,一个真正的应用程序可能是一个 POS 系统来显示所有客户,并在列表中有一个图标作为客户是否有未结订单的指示器。

4

7 回答 7

6

我想尝试使用 EXISTS,对于这种情况,它可能比连接表更好。在我的 oracle 数据库上,它的执行时间比示例查询要好一些,但这可能是特定于数据库的。

SELECT first_table.ID, CASE WHEN EXISTS (SELECT * FROM second_table WHERE first_table.ID = second_table.ID) THEN 1 ELSE 0 END FROM first_table
于 2013-06-14T11:57:21.033 回答
2

为什么不试试这个

select a.index,count(b.[table id])  
from first_table a
left join second_table b
    on a.index = b.index
group by a.index
于 2013-06-14T11:12:21.390 回答
1

两个想法:一个不涉及更改您的表格,一个涉及。首先是使用现有表的那个:

SELECT
  a.index,
  b.index IS NOT NULL,
  c.index IS NOT NULL
FROM
  a_table a
LEFT JOIN
  b_table b ON b.index = a.index
LEFT JOIN
  c_table c ON c.index = a.index
GROUP BY
  a.index, b.index, c.index

值得注意的是,如果b_table.index并且c_table.index是主键或以其他方式被索引,则此查询(以及可能任何类似的查询)将有很大帮助。

现在是另一个想法。如果可以的话,不要在 中插入一行b_tablec_table在相应行中指明某些内容a_table,而是直接在该a_table行上指明。将exists_in_b_tableexists_in_c_table列添加到a_table. 每当您在 中插入一行b_table时,a_table.exists_in_b_table = true为 中的相应行设置a_table。删除的工作量更大,因为为了更新行,您必须检查除了您刚刚删除a_table的行之外是否还有其他具有相同索引的行。但是,如果删除不频繁,这是可以接受的。b_table

于 2013-06-22T14:07:27.613 回答
1

或者您可以完全避免加入。

WITH comb AS (
SELECT index
     , 'N' as exist_ind
  FROM first_table
UNION ALL
SELECT DISTINCT 
       index
     , 'Y' as exist_ind
  FROM second_table
)
SELECT index
     , MAX(exist_ind) exist_ind
  FROM comb
 GROUP BY index
于 2013-06-21T23:20:52.933 回答
0

我不是用例专家,但会推荐加入...

即使您使用三个或更多表也有效..

SELECT t1.ID,t2.name, t3.date
FROM  Table1 t1 
LEFT OUTER JOIN Table2 t2 ON t1.ID = t2.ID
LEFT OUTER JOIN Table3 t3 ON t2.ID = t3.ID
--WHERE t1.ID = @ProductID -- this is optional condition, if want specific ID details..

这将帮助您从规范化(BCNF)表中获取数据。因为它们总是在单独的表中对数据进行分类。

我希望这会...

于 2013-06-21T09:59:01.817 回答
0

我假设您不能更改表定义,例如对列进行分区。

现在,为了获得良好的性能,您需要考虑其他正在加入主表的表。

这一切都取决于数据人口统计。

  1. 如果其他联接将按高因子折叠行,则应考虑在第一个表和第二个表之间进行联接。这将允许优化器选择最佳连接顺序,即首先与其他表连接,然后将结果行与您的第二个表连接以获得性能。

  2. 否则,您可以采用子查询方法(我建议使用存在,可能是 Mikhail 的解决方案)。

  3. 此外,如果您在同一会话中多次需要此类查询,您可以考虑创建一个临时表。

于 2013-06-20T20:20:44.667 回答
0

此查询的应用将用于两件事:

  1. 指示 first_table 中的给定行在 second_table 中至少存在一行。它是在一个列表中表明它。
  2. 搜索 first_table 中所有在 second_table 中至少有一行的行。

干得好:

SELECT  a.index, 1 as c_check  -- 1: at least one row in second_table exists for a given row in first_table
FROM    first_table a
WHERE   EXISTS
        (
            SELECT  1
            FROM    second_table b
            WHERE   a.index = b.index
        );
于 2013-06-17T15:43:45.387 回答