从三个相同的表中获取单个结果集的简单方法?

时间:2018-11-20 16:42:57

标签: sql sql-server

我正在使用的数据库具有三个具有相同列布局的表,即OPEX,NOPEX和CAPEX。我想查询所有三个具有匹配AssetId的项目,并获得一个结果集,以便我可以在自己的.Net代码中同时处理它们。

我需要知道他们来自哪张桌子。

我知道我可以使用SELECT子句中的一系列CASE做到这一点,也许使用每个非零的ID列来确定它来自哪个表。但是我必须为每一列设置一个,并且表非常宽。

还有其他解决方法吗?

2 个答案:

答案 0 :(得分:3)

为了将它们分成一组,可以结合使用UNION和EXISTS()检查。 UNION ALL将为您提供一个包含所有三个表中数据的单个结果集,对每个表进行EXISTS检查将确认您要查询的表在其他表中具有相应的记录。

SELECT *, 'OPEX' AS table_name 
FROM OPEX o
WHERE EXISTS (
SELECT 1 
FROM NOPEX n
WHERE n.asset_id = o.asset_id)
AND EXISTS (
SELECT 1 
FROM CAPEX c
WHERE c.asset_id = o.asset_id)

UNION ALL 

SELECT *, 'NOPEX' AS table_name 
FROM NOPEX n
WHERE EXISTS (
SELECT 1 
FROM Opex o
WHERE o.asset_id = n.asset_id)
AND EXISTS (
SELECT 1 
FROM CAPEX c
WHERE c.asset_id = n.asset_id)

UNION ALL 

SELECT *, 'CAPEX' AS table_name  
FROM CAPEX c
WHERE EXISTS (
SELECT 1 
FROM Opex o
WHERE o.asset_id = c.asset_id)
AND EXISTS (
SELECT 1 
FROM NOPEX n
WHERE n.asset_id = c.asset_id)

我想您也可以进行内部联接?

SELECT c.*, 'CAPEX' AS table_name  
FROM CAPEX c
INNER JOIN OPEX o
ON o.asset_id = c.asset_id
INNER JOIN NOPEX n
ON n.asset_id = c.asset_id

UNION ALL 

SELECT o.*, 'OPEX' AS table_name 
FROM OPEX o
INNER JOIN CAPEX c
ON c.asset_id = o.asset_id
INNER JOIN NOPEX n
ON n.asset_id = o.asset_id

UNION ALL 

SELECT n.*, 'NOPEX' AS table_name 
FROM NOPEX n
INNER JOIN OPEX o
ON o.asset_id = n.asset_id
INNER JOIN CAPEX c
ON c.asset_id = n.asset_id

答案 1 :(得分:0)

对dfundako的回答类似,但是要更快地解决所有三个表中AssetId的位置,而对相关表的索引的命中要少:

;with cte as (
    select
    AssetID
    from (
        select distinct
        AssetID
        from Opex
        union all
        select distinct
        AssetID
        from Nopex
        union all
        select distinct
        AssetID
        from Capex
        ) as AssetIDs
    group by AssetId
    having count(AssetId) = 3
    )

select 'Opex', * from Opex as o
inner join cte 
    on o.AssetID = cte.AssetID
union all
select 'Nopex', * from Nopex as n
inner join cte 
    on n.AssetID = cte.AssetID
union all
select 'Capex', * from Capex as c
inner join cte 
    on c.AssetID = cte.AssetID