Sql server 无法让左连接工作

Sql server 无法让左连接工作,sql-server,join,Sql Server,Join,我有一个SQL表,格式如下: TimeStamp OeprationID MachineID MachineOSVersion xxx 1 MAC1 Vista xxx 2 MAC2 Linux xxx 3 MAC2 Linux xxx 4 MAC3 MACOS 订阅信息如下: Subsc

我有一个SQL表,格式如下:

TimeStamp   OeprationID MachineID   MachineOSVersion
xxx           1         MAC1        Vista
xxx           2         MAC2        Linux
xxx           3         MAC2        Linux
xxx           4         MAC3        MACOS
订阅信息如下:

SubscriptionID  MachineID
SUB1            MAC1
SUB2            MAC2
SUB3            MAC3
SUB3            MAC3
SUB3            MAC3
我想使用左连接实现一个表,该表给出如下结果:

MachineID   MachineOSVersion Subscription
MAC1        Vista            SUB1
MAC2        Linux            SUB2
MAC3        MACOS            SUB3
operations表包含一个MachineOS版本,我希望它与机器和订阅详细信息一起显示。涉及的字段更多,但这仅用于示例

编辑: 原始问题的变化:订阅表有多个MachineID,对于这些MachineID中的每一个,我想在Operations表中查找并找出可用的“最新”MachineOS版本。由于机器操作系统可以升级,这些可能会从较旧的日期更改为较新的日期。因此,必须挑选最新的

我在使用左连接时看到的问题是,我看到生成了多个重复项。可能是因为手术台上有很多机器

SELECT DISTINCT Oepration.MachineID, Oepration.MachineOSVersion, Subscription.Subscription
FROM Oepration
LEFT JOIN Subscription
  ON Oepration.MachineID = Subscription.MachineID
“操作”应该是“操作”吗

SELECT MachineID, MachineOSVersion,       SubscriptionID AS Subscription
FROM Table1name AS op
LEFT OUTER JOIN Table2name AS sub
ON sub.MachineID = op.MachineID
ORDER BY MachineID

使用左外部联接很重要,因为它比“左联接”更兼容(它更有可能跨不同类型的数据库工作)

我只需使用一个常规的
内部联接
结果,通过
内部联接
上的附加子查询来获得所需的输出,以确保获得最新的
机器版本

子查询通过最大的
操作ID
获取每台机器的最后一个
机器版本
,但是如果需要,您可以使用另一个字段,可能是时间戳

MS SQL Server 2012架构设置

CREATE TABLE MachineTable
    (
      [TimeStamp] VARCHAR(3) ,
      [OperationID] INT ,
      [MachineID] VARCHAR(4) ,
      [MachineOSVersion] VARCHAR(6)
    );

INSERT  INTO MachineTable
        ( [TimeStamp], [OperationID], [MachineID], [MachineOSVersion] )
VALUES  ( 'xxx', 1, 'MAC1', 'Vista' ),
        ( 'xxx', 2, 'MAC2', 'Linux1' ),
        ( 'xxx', 3, 'MAC2', 'Linux2' ),
        ( 'xxx', 4, 'MAC3', 'MACOS' );

CREATE TABLE SubscriptionsTable
    (
      [SubscriptionID] VARCHAR(4) ,
      [MachineID] VARCHAR(4)
    );

INSERT  INTO SubscriptionsTable
        ( [SubscriptionID], [MachineID] )
VALUES  ( 'SUB1', 'MAC1' ),
        ( 'SUB2', 'MAC2' ),
        ( 'SUB3', 'MAC3' ),
        ( 'SUB3', 'MAC3' ),
        ( 'SUB3', 'MAC3' );
SELECT  st.MachineId ,
        st.SubscriptionId ,
        mt.MachineOSVersion,
        mt.OperationID
FROM    SubscriptionsTable st
INNER JOIN MachineTable mt ON mt.MachineId = st.MachineId 
      AND mt.OperationID = (SELECT MAX(mt2.OperationID) 
                            FROM MachineTable mt2
                            WHERE mt2.MachineId = mt.MachineId)
GROUP BY st.MachineId ,
        st.SubscriptionId ,
        mt.MachineOSVersion,
        mt.OperationID
| MACHINEID | SUBSCRIPTIONID | MACHINEOSVERSION | OPERATIONID |
|-----------|----------------|------------------|-------------|
|      MAC1 |           SUB1 |            Vista |           1 |
|      MAC2 |           SUB2 |           Linux2 |           3 |
|      MAC3 |           SUB3 |            MACOS |           4 |
查询1

CREATE TABLE MachineTable
    (
      [TimeStamp] VARCHAR(3) ,
      [OperationID] INT ,
      [MachineID] VARCHAR(4) ,
      [MachineOSVersion] VARCHAR(6)
    );

INSERT  INTO MachineTable
        ( [TimeStamp], [OperationID], [MachineID], [MachineOSVersion] )
VALUES  ( 'xxx', 1, 'MAC1', 'Vista' ),
        ( 'xxx', 2, 'MAC2', 'Linux1' ),
        ( 'xxx', 3, 'MAC2', 'Linux2' ),
        ( 'xxx', 4, 'MAC3', 'MACOS' );

CREATE TABLE SubscriptionsTable
    (
      [SubscriptionID] VARCHAR(4) ,
      [MachineID] VARCHAR(4)
    );

INSERT  INTO SubscriptionsTable
        ( [SubscriptionID], [MachineID] )
VALUES  ( 'SUB1', 'MAC1' ),
        ( 'SUB2', 'MAC2' ),
        ( 'SUB3', 'MAC3' ),
        ( 'SUB3', 'MAC3' ),
        ( 'SUB3', 'MAC3' );
SELECT  st.MachineId ,
        st.SubscriptionId ,
        mt.MachineOSVersion,
        mt.OperationID
FROM    SubscriptionsTable st
INNER JOIN MachineTable mt ON mt.MachineId = st.MachineId 
      AND mt.OperationID = (SELECT MAX(mt2.OperationID) 
                            FROM MachineTable mt2
                            WHERE mt2.MachineId = mt.MachineId)
GROUP BY st.MachineId ,
        st.SubscriptionId ,
        mt.MachineOSVersion,
        mt.OperationID
| MACHINEID | SUBSCRIPTIONID | MACHINEOSVERSION | OPERATIONID |
|-----------|----------------|------------------|-------------|
|      MAC1 |           SUB1 |            Vista |           1 |
|      MAC2 |           SUB2 |           Linux2 |           3 |
|      MAC3 |           SUB3 |            MACOS |           4 |

CREATE TABLE MachineTable
    (
      [TimeStamp] VARCHAR(3) ,
      [OperationID] INT ,
      [MachineID] VARCHAR(4) ,
      [MachineOSVersion] VARCHAR(6)
    );

INSERT  INTO MachineTable
        ( [TimeStamp], [OperationID], [MachineID], [MachineOSVersion] )
VALUES  ( 'xxx', 1, 'MAC1', 'Vista' ),
        ( 'xxx', 2, 'MAC2', 'Linux1' ),
        ( 'xxx', 3, 'MAC2', 'Linux2' ),
        ( 'xxx', 4, 'MAC3', 'MACOS' );

CREATE TABLE SubscriptionsTable
    (
      [SubscriptionID] VARCHAR(4) ,
      [MachineID] VARCHAR(4)
    );

INSERT  INTO SubscriptionsTable
        ( [SubscriptionID], [MachineID] )
VALUES  ( 'SUB1', 'MAC1' ),
        ( 'SUB2', 'MAC2' ),
        ( 'SUB3', 'MAC3' ),
        ( 'SUB3', 'MAC3' ),
        ( 'SUB3', 'MAC3' );
SELECT  st.MachineId ,
        st.SubscriptionId ,
        mt.MachineOSVersion,
        mt.OperationID
FROM    SubscriptionsTable st
INNER JOIN MachineTable mt ON mt.MachineId = st.MachineId 
      AND mt.OperationID = (SELECT MAX(mt2.OperationID) 
                            FROM MachineTable mt2
                            WHERE mt2.MachineId = mt.MachineId)
GROUP BY st.MachineId ,
        st.SubscriptionId ,
        mt.MachineOSVersion,
        mt.OperationID
| MACHINEID | SUBSCRIPTIONID | MACHINEOSVERSION | OPERATIONID |
|-----------|----------------|------------------|-------------|
|      MAC1 |           SUB1 |            Vista |           1 |
|      MAC2 |           SUB2 |           Linux2 |           3 |
|      MAC3 |           SUB3 |            MACOS |           4 |

试试这个。从
Subscription
表中查找
不同的行
,然后
将结果与另一个表左连接

SELECT SubscriptionID,
       MachineOSVersion,
       A.MachineID
FROM   (SELECT DISTINCT SubscriptionID,
                        MachineID
        FROM   Subscription) A
       LEFT JOIN operation B
              ON A.MachineID = B.MachineID 
更新

从操作表中获取最新的行。使用
窗口功能
操作
表中获取最新的行

WITH cte
     AS (SELECT Row_number()OVER (partition BY [TimeStamp], [MachineID] ORDER BY [OeprationID] DESC) rn,
                *
         FROM   operation)
SELECT SubscriptionID,
       MachineOSVersion,
       A.MachineID
FROM  (SELECT [TimeStamp],[OeprationID],[MachineID],[MachineOSVersion]
       FROM   cte
       WHERE  rn = 1) A
      RIGHT JOIN (SELECT DISTINCT SubscriptionID,MachineID
                  FROM   SubscriptionsTable) B
              ON A.MachineID = B.MachineID 

这只是另一个始终获得最新值的解决方案

SELECT
  st.MachineID,
  st.SubscriptionID
  (SELECT TOP 1 mt.MachineOSVersion FROM MachineTable mt 
   WHERE mt.MachineID = st.MachineID ORDER BY mt.TimeStamp DESC)
FROM
  (SELECT distinct(sti.MachineID),sti.SubscriptionID FROM SubscriptionsTable sti) st;
select(下面的查询)中的子查询将始终基于时间戳获取最新版本。这可能是一种比追踪操作id更好的方法,因为操作id可能并不总是给出正确的顺序(例如,一些分布式数据库不保证主键总是完全按照正确的顺序)

在FROM表中,我们选择不同的机器id以消除任何重复的机器id

(SELECT distinct(sti.MachineID),sti.SubscriptionID FROM SubscriptionsTable sti) st;
例如

小提琴的DDL: 创建表MachineTable ( [时间戳]INT, [OperationID]INT, [MachineID]VARCHAR(10), [MachineOSVersion]VARCHAR(10) );

INSERT  INTO MachineTable
        ( [TimeStamp], [OperationID], [MachineID], [MachineOSVersion] )
VALUES  ( 1415616586, 1, 'MAC1', 'Vista' ),
        ( 1416480586, 2, 'MAC2', 'Linux v1' ),
        ( 1416912586, 3, 'MAC2', 'Linux v2' ),
        ( 1416998987, 4, 'MAC3', 'MACOS' );

CREATE TABLE SubscriptionsTable
    (
      [SubscriptionID] VARCHAR(4) ,
      [MachineID] VARCHAR(4)
    );

INSERT  INTO SubscriptionsTable
        ( [SubscriptionID], [MachineID] )
VALUES  ( 'SUB1', 'MAC1' ),
        ( 'SUB2', 'MAC2' ),
        ( 'SUB3', 'MAC3' ),
        ( 'SUB3', 'MAC3' ),
        ( 'SUB3', 'MAC3' );
小提琴的SQL查询:

SELECT
  st.MachineID,
  st.SubscriptionID,
  (SELECT TOP 1 mt.MachineOSVersion FROM MachineTable mt WHERE mt.MachineID = st.MachineID ORDER BY mt.TimeStamp DESC)
FROM
  (SELECT distinct(sti.MachineID),sti.SubscriptionID FROM SubscriptionsTable sti) st;

注意:DDL基于Tanner的DDL。

确切的问题是什么?你试过哪些不起作用的?为什么要使用
左连接
?什么定义了“最新操作系统版本”?看起来这是由时间戳定义的?我已经更新了答案以反映您的编辑谢谢,我如何确保从操作表中选取“最新”条目?我总是希望只接受一个查询。当前的问题是FROM子句已经非常复杂,我无法对其进行任何更改,因此唯一需要修改的地方是左连接。那么,我可以在那里添加什么来获取“最新”的machineOS表单操作吗?@confusednerd-立即检查注意到您正在使用operationId上的max,根据原始帖子,您只需选择不同的值,然后按时间戳排序。