为什么我的左/右外连接从对面的表返回数据?

时间:2015-12-18 18:48:20

标签: sql-server

所以我有4个表,我正在尝试根据各种标签和ID加入它们。我们可以在下面查看, 我有我的顶级CTE,它从表Datalog中获取大于零的所有数据。

我的第二个CTE从Datalog获取的所有数据都等于零或等于null。

然而,做一些内连接和右外连接与每个cte然后做一个联合 CTE用于获取包含来自GblTagStructure的所有标签的最终结果以及相应的数据 结构。

其中一个要求是我的最终结果不能包含data = 0的任何标记。如果有的话 等于零,那么我应该用数据记录中记录的最新值替换该零。

这是我的最终cte所做的,之后我只是选择以我想要的格式获取所有数据。

问题是,并非所有来自GblTagStructure的标签都包含在我的最终结果中。有人告诉过我 这是不可能发生的,因为所有标签都定期收集数据。那我的错误在哪里? 我的连接错了吗? 结果表明,当我使用右外连接时,我得到位于左侧的gbltagstructure中的所有标签,当我使用左外连接时,来自右侧的一堆不需要的标签......我可能不会也正确理解加入。

所以请帮助我了解何时使用左/右外连接。

我已经包含了一些我的表的图像,没有sqlfiddle的原因是数据太多了 在我的表格中复制它。所以我正在跳跃,我们可以在没有方形的情况下解决这个问题。

declare @DateTime as Datetime
set @DateTime = '2015-12-01'

;with Data as ( select distinct a.timestamputc as times, c.name, cast(a.Data as float) as data, d.tag,a.MeterTagId, b.name as Type from DataLog a
                        inner join MeterTags b on b.metertagid = a.MeterTagId
                        inner join Meters c on c.MeterId = b.meterid
                        right outer join GblTagStructure d on d.metertagid = a.metertagid
                        --where TimestampUTC<=dateadd(day,1,dateadd(mi,-1,@DateTime)) and TimestampUTC>=dateadd(day,0,@DateTime)  and a.Data>0),
                        --where a.TimestampUTC = dateadd(d,-0,convert(date,CURRENT_TIMESTAMP,110)) and a.Data > 0),
                        where a.TimestampUTC = dateadd(d,0,'2015-12-17') and a.Data > 0 )
lesszero as (select distinct a.timestamputc as times, c.name, cast(a.Data as float) as data, d.tag, a.MeterTagId, b.name as Type from DataLog a
                        inner join MeterTags b on b.metertagid = a.MeterTagId
                        inner join Meters c on c.MeterId = b.meterid
                        right outer join gbltagstructure d on d.metertagid = a.metertagid
                        --where TimestampUTC<=dateadd(day,1,dateadd(mi,-1,@DateTime)) and TimestampUTC>=dateadd(day,0,@DateTime)   and a.Data=0 ),
                        --where a.TimestampUTC >= dateadd(d,0,convert(date,2015-12-17,110)) and a.Data = 0 )
                        where a.TimestampUTC = dateadd(d,0,'2015-12-12') and a.Data = 0 or a.data is null )
Final as(select distinct cast(times as Date) as DateTime, Name,Data,Tag from Data a 
union all 
select distinct cast(b.times as Date) as DateTime,b.name as Name,Data=(select max(data) from DataLog where timestamputc >= (select MAX(timestamputc) from DataLog where MeterTagId=b.metertagid 
and data>0) 
and MeterTagId=b.metertagid and data>0 ) , Tag
from lesszero b )

Select distinct DateTime, Name as ParameterName, Max(Data) as DataValue, Tag from Final
Group By Name, Tag, DateTime

GBLTagStructure Table

[MeterTags表] [2]

[米表] [3]

DataLog table

2 个答案:

答案 0 :(得分:1)

您对JOIN的理解是正确的。问题是你的WHERE条款。

你基本上是这样做的:

SELECT ...
FROM TableA
RIGHT OUTER JOIN TableB ON ...
WHERE TableA.SomeColumn = 'Something'

因此,您开始获取TableB中的所有行,如果TableA中没有匹配项,则TableA列中的内容为NULL。

然后,您的WHERE子句将删除TableA列为NULL的所有行。

如果将涉及TableA的WHERE子句条件移动到JOIN的ON子句,那么您将按预期从TableB获取所有行。

答案 1 :(得分:0)

当您使用left时,将ON表格过滤器移至Right Outer Join条件,否则只有匹配的结果才会被过滤,最终结果将与INNER JOIN相同

SELECT DISTINCT a.timestamputc        AS times, 
                c.NAME, 
                Cast(a.data AS FLOAT) AS data, 
                d.tag, 
                a.metertagid, 
                b.NAME                AS type 
FROM   datalog a 
       INNER JOIN metertags b 
               ON b.metertagid = a.metertagid 
                  AND a.timestamputc = Dateadd(d, 0, '2015-12-17') 
                  AND a.data > 0 
       INNER JOIN meters c 
               ON c.meterid = b.meterid 
       RIGHT OUTER JOIN gbltagstructure d 
                     ON d.metertagid = a.metertagid 
相关问题