我有三个桌子。所有这些都遵循CRUD模式进行插入和更新。我需要进行查询,根据另一个表的唯一值选择一个表中的所有最新更新,并通过连接两次将其删除:(在示例中,我省略了两个表的CRUD结构)
表COPY_HISTORY
COPY_ID | DATA_ID | STATUS | TIME |
1 | A | open | 10:34 |
1 | A | locked | 10:37 |
2 | A | open | 10:38 |
3 | B | open | 11:29 |
4 | C | open | 10:37 |
5 | D | locked | 09:34 |
表DATA_SET
DATA_ID | LOCATION |
A | 88 |
B | 77 |
C | 88 |
D | 99 |
E | 88 |
F | 88 |
表COPY_RULES
LOCATION_FROM | LOCATION_TO
55 | 110
66 | 120
77 | 120
88 | 130
99 | 130
我需要做的是从复制规则表中获取每个LOCATION_TO的状态。如果执行了副本,它将被记录在副本历史记录中,并且副本将始终覆盖位置(110,120,130)上的所有数据。
在这种情况下,位置110从未发生过复制,并且110根本不应包含在返回的数据中。即使它存在于规则中,也不相关。 120将从66和77的数据集中接收副本。但是,我们在66上还没有数据集,因此只有77是相关的。 B位于77,数据集B在11:29插入了复制历史记录,状态为打开。由于这是属于120的唯一状态,因此状态对120处于打开状态,并且位置120可能会被覆盖。
位置130,但是同时接收88和99的副本。这意味着数据集A,C,D,E和F都将复制到130中,因为它们都位于88或99中。我们有两个复制历史记录记录A的日志,记录C和D的日志。这意味着我只希望最新注册的状态,在这种情况下为10:38。
现在,我已尝试根据LOCATION_TO从COPY_HISTORY中选择最大值,但我陷入僵局,无法使LOCATION_TO唯一
我尝试:
SELECT cr.LOCATION_TO, ch.STATUS, ch.TIME FROM COPY_HISTORY ch
JOIN DATA_SET ds ON ch.DATA_ID = ds.DATA_ID
JOIN COPY_RULES cr ON cr.LOCATION_FROM = ds.LOCATION
WHERE ch.TIME = (SELECT MAX(TIME) FROM COPY_HISTORY
WHERE COPY_ID = ch.COPY_ID
AND ch.DATA_ID = ds.DATA_ID
AND ds.LOCATION = cr.LOCATION_FROM)
该选择的最大时间陈述不完整。两条AND线什么都不做。我唯一能做的就是摆脱COPY_HISTORY中的第一行,这意味着我可以获得每个COPY_ID的所有最大时间,但是我不知道如何过滤它们以仅获取每个LOCATION_TO的最大值。 >
这样做,我设法从一个LOCATION_TO中获得了最大值:
SELECT cr.LOCATION_TO, ch.STATUS, ch.TIME FROM COPY_HISTORY ch
JOIN DATA_SET ds ON ch.DATA_ID = ds.DATA_ID
JOIN COPY_RULES cr ON cr.LOCATION_FROM = ds.LOCATION
WHERE ch.TIME = (SELECT MAX(TIME) FROM COPY_HISTORY ch2, DATA_SET ds2, COPY_RULES cs2
WHERE ch2.DATA_ID = ds2.DATA_ID
AND ds2.LOCATION = cr2.LOCATION_FROM
AND cr2.LOCATION_TO = 2180)
但是,这不能解决我获取所有LOCATION_TO的状态列表的问题。
期望的输出:
LOCATION_TO | STATUS | TIME |
120 | open | 11:29 |
130 | open | 10:38 |
COPY_HISTORY中的有效行将是第3行和第4行
这是试图极大简化实际数据库结构的尝试,因此存在输入错误的风险。
DDL
create table #COPY_HISTORY (COPY_ID int, DATA_ID char(1), [STATUS] varchar(16), [TIME] time)
create table #DATA_SET (DATA_ID char(1), [LOCATION] int)
create table #COPY_RULES (LOCATION_FROM int, LOCATION_TO int)
insert into #COPY_HISTORY
values
(1,'A','open','10:34'),
(1,'A','locked','10:37'),
(2,'A','open','10:38'),
(3,'B','open','11:29'),
(4,'C','open','10:37'),
(5,'D','locked','09:34')
insert into #DATA_SET
values
('A',88),
('B',77),
('C',88),
('D',99),
('E',88),
('F',88)
insert into #COPY_RULES
values
(55,110),
(66,120),
(77,120),
(88,130),
(99,130)
答案 0 :(得分:4)
我认为该查询将为您服务。正如Ryan在评论中提到的那样,您可以使用ROW_NUMBER分析函数按时间(ORDER BY)对位置记录(PARTITION BY)进行排名,然后仅返回每个位置的第一行(RowOrder = 1)。
SELECT * FROM (
SELECT cr.LOCATION_TO, ch.STATUS, ch.TIME, ROW_NUMBER() OVER (PARTITION BY cr.LOCATION_TO ORDER BY ch.TIME desc) AS RowOrder
FROM #COPY_HISTORY ch
JOIN #DATA_SET ds ON ch.DATA_ID = ds.DATA_ID
JOIN #COPY_RULES cr ON cr.LOCATION_FROM = ds.LOCATION
) ordered_set
WHERE RowOrder = 1
答案 1 :(得分:2)
如果我正确理解了逻辑:
nssm install MDHIS_WebClient "%MDHIS2_HOME%/MDHIS_WebClient.cmd" AppDirectory %MDHIS2_HOME% DisplayName MDHIS_WebClient Start SERVICE_AUTO_START DependOnService MSSQLSERVER AppNoConsole 1 AppStopMethodConsole 30000