【问题标题】:How do I join all in one sql table and with first occurence from another table, keeping all from first table如何在一个 sql 表中加入所有内容,并从另一个表中第一次出现,保留所有来自第一个表
【发布时间】:2025-12-08 10:45:01
【问题描述】:

以下 SQLite (android Room) 查询:

(格林威治标准时间 2021.01.03 07:43 更新:我增强了 Q)

select  o.*, gi.* 
from orders as o
left join galleryitems as gi on gi.siteId = o.siteId 
order by orderId asc

这些给定的表格:

orders: unique key is orderid

o.orderId | siteId      | col1      | col2
----------+-------------+-----------+----------
456       | 1001        | o.456c1r1 | o.456c2r1 
457       | 1002        | o.457c1r1 | o.457c2r1
458       | 1003        | o.458c1r1 | o.458c2r1
459       | 1004        | o.459c1r1 | o.459c2r1
460       | 1005        | o.460c1r1 | o.460c2r1
461       | 1006        | o.461c1r1 | o.461c2r1
462       | 1007        | o.462c1r1 | o.462c2r1


galleryitems: unique key is galleryId, reference to ordertable is gi.siteId

gi.galleryID | gi.col1     | gi.col2     | gi.siteId 
-------------+-------------+-------------+----------
0001         | gi1001.c1r1 | gi1001.c2r1 | 1001      
0002         | gi1001.c1r2 | gi1001.c2r2 | 1001      
0003         | gi1002.c1r1 | gi1002.c1r1 | 1002
0004         | gi1003.c1r1 | gi1003.c1r1 | 1005
0005         | gi1003.c1r2 | gi1003.c1r2 | 1005

给出这个结果:


o.orderId | o.siteId | col1      | col2      | gi.galleryID | gi.col1     | gi.col2     | gi.siteId 
----------+----------+-----------+-----------+--------------+-------------+-------------+----------
456       | 1001     | o.456c1r1 | o.456c2r1 | 0001         | gi1001.c1r1 | gi1001.c2r1 | 1001   <-- "duplicates"   
456       | 1001     | o.456c1r1 | o.456c2r1 | 0002         | gi1001.c1r2 | gi1001.c2r2 | 1001   <-- "duplicates"
457       | 1002     | o.457c1r1 | o.457c2r1 | 0003         | gi1002.c1r1 | gi1002.c1r1 | 1002
458       | 1003     | o.458c1r1 | o.458c2r1 | <null>       | <null>      | <null>      | <null>
459       | 1004     | o.459c1r1 | o.459c2r1 | <null>       | <null>      | <null>      | <null>
460       | 1005     | o.460c1r1 | o.460c2r1 | 0004         | gi1003.c1r1 | gi1003.c1r1 | 1005   <-- "duplicates"
460       | 1005     | o.460c1r1 | o.460c2r1 | 0005         | gi1003.c1r2 | gi1003.c1r2 | 1005   <-- "duplicates"
461       | 1006     | o.461c1r1 | o.461c2r1 | <null>       | <null>      | <null>      | <null>
462       | 1007     | o.462c1r1 | o.462c2r1 | <null>       | <null>      | <null>      | <null>

正如您在下面看到的,我希望来自gi 的数据仅在它们出现时出现,但只在第一次出现时出现,因此它们不会“重复”(如果找到 gi.siteid 只需填写 inn 数据(首先出现是可以的,甚至可以计算,如果在加入期间可能的话),否则 gi 字段应该是 &lt;null&gt; ):


o.orderId | o.siteId | col1      | col2      | gi.galleryID | gi.col1     | gi.col2     | gi.siteId 
----------+----------+-----------+-----------+--------------+-------------+-------------+----------
456       | 1001     | o.456c1r1 | o.456c2r1 | 0001         | gi1001.c1r1 | gi1001.c2r1 | 1001   <-- no "duplicates"   
457       | 1002     | o.457c1r1 | o.457c2r1 | 0003         | gi1002.c1r1 | gi1002.c1r1 | 1002
458       | 1003     | o.458c1r1 | o.458c2r1 | <null>       | <null>      | <null>      | <null>
459       | 1004     | o.459c1r1 | o.459c2r1 | <null>       | <null>      | <null>      | <null>
460       | 1005     | o.460c1r1 | o.460c2r1 | 0004         | gi1003.c1r1 | gi1003.c1r1 | 1005   <-- no "duplicates"
461       | 1006     | o.461c1r1 | o.461c2r1 | <null>       | <null>      | <null>      | <null>
462       | 1007     | o.462c1r1 | o.462c2r1 | <null>       | <null>      | <null>      | <null>

我看到有很多建议,但它们无法处理 SQLite 受限库。

有什么建议吗?

使用 androidx 房间。

【问题讨论】:

  • ...只有第一次出现... 根据哪一栏?是gi.row1列的最小值吗?
  • 抱歉,我看到我的 Q 中有错误,我明天会更正它...
  • 我已经更新了我的 Q,让它更清晰一些。

标签: sqlite android-sqlite android-room


【解决方案1】:

您可以通过聚合来获取最小值为 galleryitems.row1 的行,方法是使用 SQLite 的一个不是标准 SQL 但它是 documented 的功能:

select  min(gi.row1) as row1, gi.row2, gi.siteId, o.* 
from orders as o left join galleryitems as gi 
on gi.siteId = o.siteId 
group by o.siteId
order by orderId asc 

或者使用galleryitemsrowid来定义第一次出现

select  gi.*, o.* 
from orders as o left join galleryitems as gi 
on gi.siteId = o.siteId 
group by o.siteId
having min(gi.rowid) or min(gi.rowid) is null
order by orderId asc

请参阅demo

【讨论】:

  • 感谢您的快速回答,我稍微增强了我的 Q,您的建议效果很好,我什至用计数器而不是 min(实际上是 `count(gi.siteId)' ) 然后可以收集出现次数。更好...非常感谢。
  • @RoarGrønmo 很好,如果它适合你。但是您应该知道,通过使用 COUNT() 而不是 MIN(),虽然 COUNT() 的结果是正确的,但是您为每个 siteid 获得的行是不可预测的。使用 MIN() 可以获得包含最小行 1 的行,但使用 COUNT() 不能保证获得该行。
【解决方案2】:

@forpas 将我纠正为宽阔的道路,我什至可以对其进行改进。谢谢!

select count(gi.siteId) as cc, gi.*, o.*
from orders as o
left join galleryitems as gi on gi.siteId = o.siteId
group by o.siteId 

这个结果现在变成这个结果:(注意!! group by o.siteId not gi.siteId)

cc |o.orderId | o.siteId | col1      | col2      | gi.galleryID | gi.col1     | gi.col2     | gi.siteId 
---+----------+----------+-----------+-----------+--------------+-------------+-------------+----------
2  |456       | 1001     | o.456c1r1 | o.456c2r1 | 0001         | gi1001.c1r1 | gi1001.c2r1 | 1001   <-- no "duplicates"   
1  |457       | 1002     | o.457c1r1 | o.457c2r1 | 0003         | gi1002.c1r1 | gi1002.c1r1 | 1002
0  |458       | 1003     | o.458c1r1 | o.458c2r1 | <null>       | <null>      | <null>      | <null>
0  |459       | 1004     | o.459c1r1 | o.459c2r1 | <null>       | <null>      | <null>      | <null>
2  |460       | 1005     | o.460c1r1 | o.460c2r1 | 0004         | gi1003.c1r1 | gi1003.c1r1 | 1005   <-- no "duplicates"
0  |461       | 1006     | o.461c1r1 | o.461c2r1 | <null>       | <null>      | <null>      | <null>
0  |462       | 1007     | o.462c1r1 | o.462c2r1 | <null>       | <null>      | <null>      | <null>

【讨论】:

    最近更新 更多