Sql server 无法让左连接工作
我有一个SQL表,格式如下: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
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,根据原始帖子,您只需选择不同的值,然后按时间戳排序。