[英]SQL: Getting items which have a max value in another tables column, but also match some cross table clauses
This is probably a really basic question but I have spend a lot of time on this. 这可能是一个非常基本的问题,但是我花了很多时间在这上面。
I have 2 Tables: 我有2张桌子:
Files 档
| FileId | Type | FolderId |
----------------------------
| 1 | txt | 11 |
| 2 | xml | 15 |
| 3 | xml | 17 |
| 4 | txt | 19 |
Folders 文件夹
| FolderId | path | version | typeId |
-------------------------------------------
| 11 | //c:/here | 1 | 1 |
| 19 | //c:/here | 3 | 1 |
| 15 | //c:/dummy| 6 | 1 |
| 17 | //c:/dummy| 4 | 1 |
I want it to return: All info from Files
, with the highest Folder.Version
number, where the Files.type
, Folders.path
and Folders.typeID
all match. 我希望它返回:来自Files
所有信息,其中Folder.Version
编号最高,其中Files.type
, Folders.path
和Folders.typeID
都匹配。
Essentially I need to group by Files.type
, where Folders.path
& Folders.typeID
are the same. 本质上,我需要按Files.type
,其中Folders.path
和Folders.typeID
相同。 Then return the item with the max version field for each group. 然后返回每个组的“最大版本”字段的项目。
So in the example above I would want the output: 因此,在上面的示例中,我需要输出:
| FileId | Type | FolderId |
----------------------------
| 2 | xml | 15 |
| 4 | txt | 19 |
So far I have the query below, which I think is ok for getting the items with the highest version number when TypeId and path match (I think????). 到目前为止,我有下面的查询,我认为可以在TypeId和path匹配时获取具有最高版本号的项目(我认为吗???)。 But I cannot figure out how to group by Files.Type. 但我不知道如何按Files.Type进行分组。
SELECT * FROM Files
WHERE FileId IN (
SELECT FileId FROM Files
WHERE FolderId IN (
SELECT fo.FolderId
FROM Folders fo
LEFT JOIN Folders fo2
ON fo.Path = fo2.Path AND fo.TypeId = fo2.TypeId
AND fo.Version < fo2.Version
WHERE fo2.Version IS NULL
)
)
Can anyone explain how I can get this query done? 谁能解释我如何完成此查询? I have a feeling I need some group by statements but I can't figure it out! 我觉得我需要一些总结,但我无法弄清楚!
This is SQL server 2012. 这是SQL Server 2012。
You didn't specify a verson of SQL Server. 您没有指定SQL Server的版本。
select Files.*
from
Files inner join
(
select f1.FolderId
from Folders f1 inner join
(
select TypeId, Path, max(Version) as MaxVersion
from Folders
group TypeId, Path
) as f2
on f2.TypeId = f1.TypeId and f2.Path = f1.Path f2.MaxVersion = f1.Version
) Folders
on Folders.FolderId = Files.FolderId
If you have a later edition of SQL Server then this should work too: 如果您有更高版本的SQL Server,那么它也应该起作用:
select Files.*
from
Files inner join
(
select first_value(FolderId)
over (partition by TypeId, Path order by Version desc) as FolderId
from Folders
) Folders
on Folders.FolderId = Files.FolderId
EDIT: Maybe this is the fix per your comment: 编辑:也许这是根据您的评论的修复程序:
select Files.*
from
Files fi inner join Folders fo on fo.FolderId = fi.FolderId
inner join
(
select "Type", TypeId, Path, max(Version) as MaxVersion
from Files fi2 inner join Folders fo2 on fo2.FolderId = fi2.FolderId
group "Type", TypeId, Path
) as mv
on mv."Type" = fi."Type"
and mv.TypeId = fo.TypeId and mv.Path = fo.Path
and mv.MaxVersion = fo.Version
I'm in a rush but I think this might work on SQL Server 2012: 我很着急,但我认为这可能适用于SQL Server 2012:
select distinct
first_value(FileId)
over (partition by "Type", TypeId, Path order by Version desc) as FileId,
"Type",
first_value(fo.FolderId)
over (partition by "Type", TypeId, Path order by Version desc) as FolderId
from
Files fi inner join Folders fo on fo.FolderId = fi.FolderId
Give this a shot: 试一下:
select f.*
from files f
inner join folders dir on f.folderid = dir.folderid
inner join (
select type, max(version) maxver
from files fi
inner join folders fo on fi.folderid = fo.folderid
group by type
) t on f.type = t.type and dir.version = t.maxver
Result: 结果:
| fileid | type | folderid |
|--------|------|----------|
| 4 | txt | 19 |
| 2 | xml | 15 |
Since SQLFiddle SQL Server 2008 and 2014 were not responding well, I created an example with MySQL here: http://sqlfiddle.com/#!9/7abd4/13 . 由于SQLFiddle SQL Server 2008和2014的响应不佳,因此我在此处使用MySQL创建了一个示例: http ://sqlfiddle.com/#!9/7abd4/13。 I expect the query results to be identical for SQL Server 2012. 我希望查询结果对于SQL Server 2012是相同的。
Simple top-1-per-group, isn't it? 简单的每组前1名,不是吗?
One possible variant using ROW_NUMBER
. 一种使用ROW_NUMBER
可能变体。
PARTITION BY Files.Type, Folders.path, Folders.typeId
define the groups, ORDER BY Folders.version DESC
define which row to pick for each group. PARTITION BY Files.Type, Folders.path, Folders.typeId
定义组, ORDER BY Folders.version DESC
定义为每个组选择哪一行。
More efficient than self-join. 比自我加入更有效。
WITH
CTE AS
(
SELECT
Files.FileId
,Files.Type
,Files.FolderId
,Folders.path
,Folders.typeId
,Folders.version
,ROW_NUMBER() OVER (
PARTITION BY Files.Type, Folders.path, Folders.typeId
ORDER BY Folders.version DESC) AS rn
FROM
Files
INNER JOIN Folders ON Folders.FolderId = Files.FolderId
)
SELECT *
FROM CTE
WHERE rn = 1
;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.