SQL 选择由 Ids 标识并由另一个表中的特定类型过滤的行列表中的所有第一项
Posted
技术标签:
【中文标题】SQL 选择由 Ids 标识并由另一个表中的特定类型过滤的行列表中的所有第一项【英文标题】:SQL Select all first items in a list of rows identified by Ids and filtered by a specific Type in another table 【发布时间】:2021-12-30 18:40:21 【问题描述】:我需要创建一个以 ID 为键的表,其中新表中的一列的值是输入到另一个表的列中的最早值,其中行共享相同的 ID 并具有特定的类型标签。
例如,假设我想为每种水果输入名称和第一个值,输入类型为 A:
这些是我的桌子:
表 1
Key | ID | Name |
---|---|---|
1 | 1 | Cherry |
2 | 2 | Grape |
表2
Key | ID | Value | EntryNum | EntryType |
---|---|---|---|---|
1 | 1 | 21 | 1 | A |
2 | 1 | 32 | 2 | B |
3 | 1 | 4 | 3 | B |
4 | 1 | 15 | 4 | A |
5 | 2 | 3 | 1 | B |
6 | 2 | 8 | 2 | A |
7 | 2 | 16 | 3 | B |
这就是我想要的结果:
表3
ID | Name | EarliestEntry |
---|---|---|
1 | Cherry | 21 |
2 | Grape | 8 |
我尝试了以下查询,但它只是为所有 EarliestEntry 返回相同的值:
SELECT TABLE1.ID, TABLE2.Name,
(SELECT Value FROM (SELECT ROW_NUMBER() OVER (ORDER BY TABLE2.EntryNum)
as row_num, Value FROM TABLE2
WHERE TABLE2.ID = TABLE1.ID AND TABLE2.EntryType = 'A')
AS sub
WHERE row_num = 1) AS EarliestEntry
INTO TABLE3
FROM TABLE2
INNER JOIN TABLE1 ON TABLE1.ID = TABLE2.ID
GROUP BY TABLE1.ID, TABLE2.Type, TABLE2.EntryNum
非常感谢您对此的帮助。谢谢
【问题讨论】:
【参考方案1】:如果您想使用 ROW_NUMBER 函数,那么您需要将它放在 TABLE1 上并添加一个分区,如下所示:
WITH rn AS(
SELECT a.Key, ROW_NUMBER() OVER(PARTITION BY a.ID ORDER BY a.EntryNum) AS rn
FROM TABLE2 AS a
)
SELECT b.Name, a.Value AS EarliestValue
FROM TABLE2 AS a
INNER JOIN TABLE1 AS b ON b.ID = a.ID
INNER JOIN rn AS rn ON rn.key = a.key
WHERE rn.rn = 1
在您的示例中,您跳过了 PARTITION BY 子句,因此您只需获得 TABLE2 中所有值的数字。而不是每个 ID 的数字按升序排列的值。
【讨论】:
【参考方案2】:根据您对三个表 TABLE1、TABLE2 和 TABLE3 的描述。
我稍微修改了你的脚本。感谢 Dale K 的评论,我用一些话解释了解决方案:第一次选择中显示的字段 TABLE2.Name 是错误的,因为 [name] 属于 TABLE1,所以正确的语法是 TABLE1.name。并且在 GROUP BY 子句中,字段 TABLE2.Type 可能会替换为 TABLE1.name 以符合聚合标准。所以脚本变成了:
SELECT DISTINCT table1.id, table1.name,
(SELECT Value FROM (SELECT ROW_NUMBER() OVER (ORDER BY table2.EntryNum)
as row_num, Value FROM table2
WHERE table2.id = table1.id AND table2.EntryType = 'A')
AS sub
WHERE row_num = 1) AS EarliestEntry
INTO table3
FROM table2
INNER JOIN table1 ON table1.id = table2.id
GROUP BY table1.id, table1.name, table2.entrynum;
Here, you can verify the output 与 fiddle
【讨论】:
一个好的答案除了提供工作代码外,还可以用文字解释解决方案是什么。 请将您的解释放在您的回答中,而不是放在最终会被删除的评论中。【参考方案3】:你把事情复杂化了。
只需对Table2
进行分区并获取行号,然后将其加入Table1
并仅过滤行号1
SELECT
t1.Id,
t1.Name,
EarliestEntry = t2.Value
FROM Table1 t1
JOIN (
SELECT *,
rn = ROW_NUMBER() OVER (PARTITION BY t2.ID ORDER BY t2.EntryNum)
FROM Table2 t2
WHERE t2.EntryType = 'A'
) t2 ON t2.ID = t1.ID AND t2.rn = 1;
db<>fiddle
【讨论】:
以上是关于SQL 选择由 Ids 标识并由另一个表中的特定类型过滤的行列表中的所有第一项的主要内容,如果未能解决你的问题,请参考以下文章