连接两列匹配的表
Joining tables where two columns match
我有一个关于各种计算机部件和价格的小型数据库。有 2 tables,零件和价格。
零件:
partID desc mfgr timeStamp
---------- ---------- ---------- ----------
1 RAM Crucial 1
2 MOBO MSI 1
3 I7 970 Intel 1
1 RAM Crucial 2
价格:
productID qty price timeStamp
---------- ---------- ---------- ----------
1 1 50.0 1
1 2 100.0 1
1 3 130.0 1
2 1 140.0 1
3 1 499.99 1
3 1 449.99 2
1 4 150.0 2
2 1 150.0 2
1 1 40.0 2
1 4 200.0 3
我需要从具有最新时间戳的零件中获取所有内容,并且 GROUP_CONCAT(price) 用于匹配 partID 和时间戳的所有价格。所以输出应该是这样的:
partID desc mfgr timeStamp GROUP_CONCAT(price)
---------- ---------- ---------- ---------- -------------------
1 RAM Crucial 2 150.0,40
2 MOBO MSI 1 140.0
3 I7 970 Intel 1 499.99
我真的很接近,但还没有得到正确的结果。我试过了
SELECT * FROM Parts INNER JOIN
(SELECT partID, MAX(Parts.timeStamp) as maxTS, GROUP_CONCAT(price) FROM
Parts, Prices WHERE partID = Prices.productID GROUP BY partID) grouped
ON Parts.partID = grouped.partID AND Parts.timeStamp = grouped.maxTS;
但这会从零件 ID 匹配的定价 table 获取所有内容,无论时间戳是否匹配。
partID desc mfgr timeStamp partID maxTS GROUP_CONCAT(price)
---------- ---------- ---------- ---------- ---------- ---------- -------------------
2 MOBO MSI 1 2 1 140.0,150.0
3 I7 970 Intel 1 3 1 449.99,499.99
1 RAM Crucial 2 1 2 40.0,50.0,100.0,130
所以我将命令更改为
SELECT * FROM Parts INNER JOIN
(SELECT partID, MAX(Parts.timeStamp) AS maxTS, GROUP_CONCAT(price)
FROM Parts, Prices
WHERE partID = Prices.productID AND (SELECT MAX(parts.timestamp) FROM Parts) = Prices.timeStamp) grouped
ON Parts.partID = grouped.partID AND Parts.timeStamp = grouped.maxTS;
但这只会匹配定价中具有最大时间戳的行。 (这是 2)
我在这里做错了什么?
您所犯的错误是您在过滤出您需要的条目之前对价格条目进行了分组。因此,您的 grouped
子查询将包含 partID
的所有价格,并且以后无法将它们分开,因为它们是分组的。
解决此类问题的最佳方法是将您的查询分解成您需要的部分。
你说:
I need to grab everything from Parts that has the most recent
timestamp
那么,让我们开始吧。请注意,这几乎需要一个子查询,或 "pivot",因为 RDBMS 不能很好地让您在依赖于其他行的条件下选择一行(在这种情况下,selecting某些组中某个字段最大的行)。我们将调用此子查询 aux
,并将其用于 parts
中与满足条件的 partID
/timeStamp
组合匹配的 select 条目:
select * from parts,
(select partId, max(timeStamp) maxts from parts group by partId) aux
where parts.partId = aux.partId and parts.timeStamp = aux.maxts
这是使用隐式连接,您也可以使用 JOIN
语法重写此查询。我个人避免使用 JOIN
语法,除非我需要 left 或其他特殊连接:
select * from parts
join (select partId, max(timeStamp) maxts from parts group by partId) aux
on parts.partId = aux.partId and parts.timeStamp = aux.maxts
现在,您想以相同 ID/timestamp 的价格加入它,但将价格组合在一起(如 GROUP_CONCAT
)。这里的关键是只有 select(在分组之前发生)匹配 "latest" 部分条目的价格条目。
因为第一个查询产生的输出可以直接与价格 tables 连接,查询只需要扩展以包括价格 table 和分组:
select parts.partid, parts.desc, group_concat(prices.price) from
parts, prices, (
select partId, max(timeStamp) maxts from parts group by partId) aux
where
parts.partId = aux.partId and
parts.timeStamp = aux.maxts and
prices.productID = parts.partid and
prices.timestamp = parts.timestamp
group by parts.partid, parts.desc
这也可以使用 JOIN
语法重写:
select parts.partid, parts.desc, group_concat(prices.price)
from parts
join (select partId, max(timeStamp) maxts from parts group by partId) aux
on parts.partId = aux.partId and parts.timeStamp = aux.maxts
join prices on prices.productID = parts.partid and prices.timestamp = parts.timestamp
group by parts.partid, parts.desc
这个查询有点复杂,根据数据集,以不同的方式重写它可能是有益的,以确保数据库理解(对优化器有利)首先过滤的内容。我们可以将过滤后的 "parts" 移动到它自己的子查询中(称之为 bux
),然后将其与 prices
table:
连接起来
select bux.partid, bux.desc, group_concat(prices.price) from prices
join (
select parts.partId, parts.desc, aux.maxts
from parts join
(select partId, max(timeStamp) maxts from parts group by partId) aux
on parts.partId = aux.partId and parts.timeStamp = aux.maxts
) bux
on prices.productID = bux.partid and prices.timestamp = bux.maxts
group by bux.partid, bux.desc
如果你检查两者之间的执行计划,你会发现不同之处。选择在生产中使用哪一个取决于哪一个表现更好。
我有一个关于各种计算机部件和价格的小型数据库。有 2 tables,零件和价格。
零件:
partID desc mfgr timeStamp
---------- ---------- ---------- ----------
1 RAM Crucial 1
2 MOBO MSI 1
3 I7 970 Intel 1
1 RAM Crucial 2
价格:
productID qty price timeStamp
---------- ---------- ---------- ----------
1 1 50.0 1
1 2 100.0 1
1 3 130.0 1
2 1 140.0 1
3 1 499.99 1
3 1 449.99 2
1 4 150.0 2
2 1 150.0 2
1 1 40.0 2
1 4 200.0 3
我需要从具有最新时间戳的零件中获取所有内容,并且 GROUP_CONCAT(price) 用于匹配 partID 和时间戳的所有价格。所以输出应该是这样的:
partID desc mfgr timeStamp GROUP_CONCAT(price)
---------- ---------- ---------- ---------- -------------------
1 RAM Crucial 2 150.0,40
2 MOBO MSI 1 140.0
3 I7 970 Intel 1 499.99
我真的很接近,但还没有得到正确的结果。我试过了
SELECT * FROM Parts INNER JOIN
(SELECT partID, MAX(Parts.timeStamp) as maxTS, GROUP_CONCAT(price) FROM
Parts, Prices WHERE partID = Prices.productID GROUP BY partID) grouped
ON Parts.partID = grouped.partID AND Parts.timeStamp = grouped.maxTS;
但这会从零件 ID 匹配的定价 table 获取所有内容,无论时间戳是否匹配。
partID desc mfgr timeStamp partID maxTS GROUP_CONCAT(price)
---------- ---------- ---------- ---------- ---------- ---------- -------------------
2 MOBO MSI 1 2 1 140.0,150.0
3 I7 970 Intel 1 3 1 449.99,499.99
1 RAM Crucial 2 1 2 40.0,50.0,100.0,130
所以我将命令更改为
SELECT * FROM Parts INNER JOIN
(SELECT partID, MAX(Parts.timeStamp) AS maxTS, GROUP_CONCAT(price)
FROM Parts, Prices
WHERE partID = Prices.productID AND (SELECT MAX(parts.timestamp) FROM Parts) = Prices.timeStamp) grouped
ON Parts.partID = grouped.partID AND Parts.timeStamp = grouped.maxTS;
但这只会匹配定价中具有最大时间戳的行。 (这是 2)
我在这里做错了什么?
您所犯的错误是您在过滤出您需要的条目之前对价格条目进行了分组。因此,您的 grouped
子查询将包含 partID
的所有价格,并且以后无法将它们分开,因为它们是分组的。
解决此类问题的最佳方法是将您的查询分解成您需要的部分。
你说:
I need to grab everything from Parts that has the most recent timestamp
那么,让我们开始吧。请注意,这几乎需要一个子查询,或 "pivot",因为 RDBMS 不能很好地让您在依赖于其他行的条件下选择一行(在这种情况下,selecting某些组中某个字段最大的行)。我们将调用此子查询 aux
,并将其用于 parts
中与满足条件的 partID
/timeStamp
组合匹配的 select 条目:
select * from parts,
(select partId, max(timeStamp) maxts from parts group by partId) aux
where parts.partId = aux.partId and parts.timeStamp = aux.maxts
这是使用隐式连接,您也可以使用 JOIN
语法重写此查询。我个人避免使用 JOIN
语法,除非我需要 left 或其他特殊连接:
select * from parts
join (select partId, max(timeStamp) maxts from parts group by partId) aux
on parts.partId = aux.partId and parts.timeStamp = aux.maxts
现在,您想以相同 ID/timestamp 的价格加入它,但将价格组合在一起(如 GROUP_CONCAT
)。这里的关键是只有 select(在分组之前发生)匹配 "latest" 部分条目的价格条目。
因为第一个查询产生的输出可以直接与价格 tables 连接,查询只需要扩展以包括价格 table 和分组:
select parts.partid, parts.desc, group_concat(prices.price) from
parts, prices, (
select partId, max(timeStamp) maxts from parts group by partId) aux
where
parts.partId = aux.partId and
parts.timeStamp = aux.maxts and
prices.productID = parts.partid and
prices.timestamp = parts.timestamp
group by parts.partid, parts.desc
这也可以使用 JOIN
语法重写:
select parts.partid, parts.desc, group_concat(prices.price)
from parts
join (select partId, max(timeStamp) maxts from parts group by partId) aux
on parts.partId = aux.partId and parts.timeStamp = aux.maxts
join prices on prices.productID = parts.partid and prices.timestamp = parts.timestamp
group by parts.partid, parts.desc
这个查询有点复杂,根据数据集,以不同的方式重写它可能是有益的,以确保数据库理解(对优化器有利)首先过滤的内容。我们可以将过滤后的 "parts" 移动到它自己的子查询中(称之为 bux
),然后将其与 prices
table:
select bux.partid, bux.desc, group_concat(prices.price) from prices
join (
select parts.partId, parts.desc, aux.maxts
from parts join
(select partId, max(timeStamp) maxts from parts group by partId) aux
on parts.partId = aux.partId and parts.timeStamp = aux.maxts
) bux
on prices.productID = bux.partid and prices.timestamp = bux.maxts
group by bux.partid, bux.desc
如果你检查两者之间的执行计划,你会发现不同之处。选择在生产中使用哪一个取决于哪一个表现更好。