Sql 联接表上的Where子句
有关下表: 房间Sql 联接表上的Where子句,sql,postgresql,Sql,Postgresql,有关下表: 房间 +----+--------+ | ID | NAME | +----+--------+ | 1 | ROOM_1 | | 2 | ROOM_2 | +----+--------+ 房间状态 +----+---------+------+------------------------+ | ID | ROOM_ID | OPEN | DATE | +----+---------+------+------------------
+----+--------+
| ID | NAME |
+----+--------+
| 1 | ROOM_1 |
| 2 | ROOM_2 |
+----+--------+
房间状态
+----+---------+------+------------------------+
| ID | ROOM_ID | OPEN | DATE |
+----+---------+------+------------------------+
| 1 | 1 | 1 | 2000-01-01 00:00:00 |
| 2 | 2 | 1 | 2000-01-01 00:00:00 |
| 3 | 2 | 0 | 2000-01-06 00:00:00 |
+----+---------+------+------------------------+
存储的数据是具有上次更改状态的文件室:
- _1房间于2000-01-01 00:00开放
- 2号房间于2000-01-01 00:00开放
- _2房间于2000-01-06 00:00关闭
SELECT ROOM.NAME
FROM ROOM
INNER JOIN ROOM_STATE ON ROOM.ID = ROOM_STATE.ROOM_ID
WHERE ROOM_STATE.OPEN = 1
之所以选择房间1和房间2,是因为带有ID
2
的房间状态处于打开状态
SQL FIDLE:您可以使用以下查询:
SELECT R.ID, R.NAME
FROM ROOM AS R
INNER JOIN ROOM_STATE AS RS ON R.ID = RS.ROOM_ID AND RS.OPEN = 1
LEFT JOIN ROOM_STATE AS RS2 ON R.ID = RS2.ROOM_ID AND RS2.OPEN = 0 AND RS2.DATE > RS.date
WHERE RS2.ID IS NULL
这将返回所有与“打开”状态相关且与日期晚于“打开”状态日期的“关闭”状态无关的房间。您可以使用以下查询:
SELECT R.ID, R.NAME
FROM ROOM AS R
INNER JOIN ROOM_STATE AS RS ON R.ID = RS.ROOM_ID AND RS.OPEN = 1
LEFT JOIN ROOM_STATE AS RS2 ON R.ID = RS2.ROOM_ID AND RS2.OPEN = 0 AND RS2.DATE > RS.date
WHERE RS2.ID IS NULL
这将返回与“打开”状态相关的所有房间,并且与日期晚于“打开”状态日期的“关闭”状态无关。在Postgres中,我建议在上进行区分:
select distinct on (rs.room_id) r.name, rs.*
from room_state rs join
room r
on rs.room_id = r.id
order by rs.room_id, rs.date desc;
distinct on
是专为Postgres设计的。它保证每个房间的结果只有一行(这是您想要的)。所选行是遇到的第一行,因此将选择日期最大的行
另一个有趣的方法是使用横向连接:
select r.*, rs.*
from room r left join lateral
(select rs.*
from room_state rs
where rs.room_id = r.id
order by rs.date desc
fetch first 1 row only
) rs;
在Postgres中,我建议您在
上使用distinct:
select distinct on (rs.room_id) r.name, rs.*
from room_state rs join
room r
on rs.room_id = r.id
order by rs.room_id, rs.date desc;
distinct on
是专为Postgres设计的。它保证每个房间的结果只有一行(这是您想要的)。所选行是遇到的第一行,因此将选择日期最大的行
另一个有趣的方法是使用横向连接:
select r.*, rs.*
from room r left join lateral
(select rs.*
from room_state rs
where rs.room_id = r.id
order by rs.date desc
fetch first 1 row only
) rs;
如果您可以保证每次打开都有一个关闭,并且总是这样,那么您也可以使用这个疯狂的sql;)
如果您可以保证每次打开都有一个关闭,并且总是这样,那么您也可以使用这个疯狂的sql;)
有几种方法可以剥这只猫的皮@GiorgosBetsos的答案是一种方式。另一个:
WITH Numbered_Status AS
(
SELECT
id,
room_id,
open,
ROW_NUMBER() OVER (PARTITION BY room_id ORDER BY date DESC) AS row_num
FROM
Room_State
)
SELECT
R.id,
R.name,
S.open
FROM
Numbered_Status S
INNER JOIN Room R ON R.room_id = S.room_id
WHERE
row_num = 1 AND
open = 1
您还可以使用不存在
:
SELECT
R.id,
R.name,
S.open
FROM
Room_State S
INNER JOIN Room R ON R.id = S.room_id
WHERE
S.open = 1 AND
NOT EXISTS
(
SELECT *
FROM Room_State S2
WHERE
S2.room_id = S.room_id AND
S2.date > S.date
)
有几种方法可以剥这只猫的皮@GiorgosBetsos的答案是一种方式。另一个:
WITH Numbered_Status AS
(
SELECT
id,
room_id,
open,
ROW_NUMBER() OVER (PARTITION BY room_id ORDER BY date DESC) AS row_num
FROM
Room_State
)
SELECT
R.id,
R.name,
S.open
FROM
Numbered_Status S
INNER JOIN Room R ON R.room_id = S.room_id
WHERE
row_num = 1 AND
open = 1
您还可以使用不存在
:
SELECT
R.id,
R.name,
S.open
FROM
Room_State S
INNER JOIN Room R ON R.id = S.room_id
WHERE
S.open = 1 AND
NOT EXISTS
(
SELECT *
FROM Room_State S2
WHERE
S2.room_id = S.room_id AND
S2.date > S.date
)
可能的解决方案,其中连接条件位于想要的房间\状态行上:
SELECT R.ID, R.NAME
FROM ROOM AS R
INNER JOIN ROOM_STATE AS RS ON R.ID = RS.ROOM_ID
AND RS.DATE = (
SELECT DATE
FROM ROOM_STATE
WHERE ROOM_ID = R.ID
ORDER BY DATE DESC
LIMIT 1
)
WHERE RS.OPEN = 1
可能的解决方案,其中连接条件位于想要的房间\状态行上:
SELECT R.ID, R.NAME
FROM ROOM AS R
INNER JOIN ROOM_STATE AS RS ON R.ID = RS.ROOM_ID
AND RS.DATE = (
SELECT DATE
FROM ROOM_STATE
WHERE ROOM_ID = R.ID
ORDER BY DATE DESC
LIMIT 1
)
WHERE RS.OPEN = 1
用您正在使用的数据库标记您的问题。完成。它不可能是纯sql答案?在sql世界中,日期函数通常是特定于供应商的。此外,有些产品不支持窗口函数和/或通用表表达式,甚至不支持ANSI标准中的部分。如果您想要一个与数据库无关的答案,那么您可以要求一个具体的答案,但它可能不如针对您正在使用的特定数据库定制的答案那么理想。@GordonLinoff感谢您的精确性!用您正在使用的数据库标记您的问题。完成。它不可能是纯sql答案?在sql世界中,日期函数通常是特定于供应商的。此外,有些产品不支持窗口函数和/或通用表表达式,甚至不支持ANSI标准中的部分。如果您想要一个与数据库无关的答案,那么您可以要求一个具体的答案,但它可能不如针对您正在使用的特定数据库定制的答案那么理想。@GordonLinoff感谢您的精确性!你好我想继续加入。我把它添加到问题中。@bux。这只会添加一个额外的联接(以及选择中的列)。您好。我想继续加入。我把它添加到问题中。@bux。这只会添加一个额外的联接(以及选择中的列)。