我遇到了一个问题,我需要运行一个Query,它应该从主表中获取一些行,并且如果主表的键存在于子表中(一对多关系),则有一个指示符。
查询可能是这样的:
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不允许触发器并通过代码跟踪它是太冒险了。
解决这个问题的好方法是什么?
此查询的应用将包含两件事:
我刚发现的另一个选择:
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系统,以显示所有客户端,并在列表中有一个图标作为指示客户端已打开订单。
答案 0 :(得分:6)
尝试使用EXISTS,我认为,对于这种情况,它可能比连接表更好。在我的oracle db上,它提供了比示例查询更好的执行时间,但这可能是特定于数据库的。
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
答案 1 :(得分: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
答案 2 :(得分: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
答案 3 :(得分: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_table
或c_table
中插入一行来表明a_table
中相应行的内容,请直接在a_table
行上指明。将exists_in_b_table
和exists_in_c_table
列添加到a_table
。每当您在b_table
中插入一行时,请为a_table.exists_in_b_table = true
中的相应行设置a_table
。删除是更多的工作,因为为了更新a_table
行,您必须检查b_table
中的任何行,而不是您刚删除的中具有相同索引的行。但是,如果删除很少,则可以接受。
答案 4 :(得分:0)
此查询的应用将包含两件事:
- 表示first_table中给定行中至少存在second_table中的一行。它是在列表中指出的。
- 搜索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
);
答案 5 :(得分:0)
我假设您无法更改表格定义,例如对列进行分区。
现在,为了获得良好的性能,您需要考虑加入主表的其他表。
这完全取决于数据的人口统计数据。
如果其他连接将按高因子折叠行,则应考虑在第一个表和第二个表之间进行连接。这将允许优化器选择最佳连接顺序,即首先与其他表连接,然后与第二个表连接的结果行获得性能。
否则,您可以采用子查询方法(我建议使用exists,可能是Mikhail的解决方案)。
此外,如果您在同一会话中多次需要此类查询,则可以考虑创建临时表。
答案 6 :(得分: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)表中获取数据..因为它们总是在单独的表中对具有自然类型的数据进行分类..
我希望这会......