SQL Server:如何加入第一行
我将使用一个具体的但假设的示例。
每个订单通常只有一个订单项 :
命令:
OrderGUID OrderNumber
========= ============
{FFB2...} STL-7442-1
{3EC6...} MPT-9931-8A
LineItems:
LineItemGUID Order ID Quantity Description
============ ======== ======== =================================
{098FBE3...} 1 7 prefabulated amulite
{1609B09...} 2 32 spurving bearing
但偶尔会有一个包含两个订单项的订单:
LineItemID Order ID Quantity Description
========== ======== ======== =================================
{A58A1...} 6,784,329 5 pentametric fan
{0E9BC...} 6,784,329 5 differential girdlespring
通常在向用户显示订单时:
SELECT Orders.OrderNumber, LineItems.Quantity, LineItems.Description
FROM OrdersINNER JOIN LineItems ON Orders.OrderID = LineItems.OrderID
我想在订单上显示单个项目。 但是,如果这个偶然的订单包含两个(或多个)项目,这些订单将看起来是重复的 :
OrderNumber Quantity Description
=========== ======== ====================
STL-7442-1 7 prefabulated amulite
MPT-9931-8A 32 spurving bearing
KSG-0619-81 5 panametric fan
KSG-0619-81 5 differential girdlespring
我真正想要的是让SQL Server 只选择一个 ,因为这样就足够了 :
OrderNumber Quantity Description
=========== ======== ====================
STL-7442-1 7 prefabulated amulite
MPT-9931-8A 32 differential girdlespring
KSG-0619-81 5 panametric fan
如果我喜欢冒险,可以向用户显示一个省略号,以表明有多个:
OrderNumber Quantity Description
=========== ======== ====================
STL-7442-1 7 prefabulated amulite
MPT-9931-8A 32 differential girdlespring
KSG-0619-81 5 panametric fan, ...
所以问题是如何
- 消除“重复”行
- 仅连接到其中一行,以避免重复
第一次尝试
我的第一个天真的尝试是仅加入“ TOP 1 ”行项目:
SELECT Orders.OrderNumber, LineItems.Quantity, LineItems.Description
FROM OrdersINNER JOIN (SELECT TOP 1 LineItems.Quantity, LineItems.DescriptionFROM LineItemsWHERE LineItems.OrderID = Orders.OrderID) LineItems2ON 1=1
但这给出了错误:
列或前缀“订单”不
与表名或别名匹配
在查询中使用。
大概是因为内部选择看不到外部表。
#1楼
我知道这个问题是在不久前回答的,但是当处理大型数据集时,嵌套查询的成本可能很高。 这是另一种解决方案,其中嵌套查询将只运行一次,而不是针对返回的每一行。
SELECT Orders.OrderNumber,LineItems.Quantity, LineItems.Description
FROM OrdersINNER JOIN (SELECTOrders.OrderNumber,Max(LineItem.LineItemID) AS LineItemIDFROMOrders INNER JOIN LineItemsON Orders.OrderNumber = LineItems.OrderNumberGROUP BY Orders.OrderNumber) AS Items ON Orders.OrderNumber = Items.OrderNumberINNER JOIN LineItems ON Items.LineItemID = LineItems.LineItemID
#2楼
尝试了十字架,效果很好,但需要更长的时间。 调整行列以具有最大数量并添加组,以保持速度并删除多余的记录。
这是调整后的查询:
SELECT Orders.OrderNumber, max(LineItems.Quantity), max(LineItems.Description)
FROM OrdersINNER JOIN LineItems ON Orders.OrderID = LineItems.OrderID
Group by Orders.OrderNumber
#3楼
SELECT Orders.OrderNumber, LineItems.Quantity, LineItems.Description
FROM Orders
JOIN LineItems
ON LineItems.LineItemGUID =(SELECT TOP 1 LineItemGUID FROM LineItemsWHERE OrderID = Orders.OrderID)
在SQL Server 2005
及更高版本中,您可以将INNER JOIN
替换为CROSS APPLY
:
SELECT Orders.OrderNumber, LineItems2.Quantity, LineItems2.Description
FROM Orders
CROSS APPLY(SELECT TOP 1 LineItems.Quantity, LineItems.DescriptionFROM LineItemsWHERE LineItems.OrderID = Orders.OrderID) LineItems2
请注意,没有ORDER BY
TOP 1
不是确定性的:此查询为每个订单提供一个订单项,但未定义为哪个订单项。
即使基础没有变化,多次调用查询也可以为同一订单提供不同的订单项。
如果要确定顺序,则应在最里面的查询中添加ORDER BY
子句。
#4楼
您可以这样做:
SELECT Orders.OrderNumber, LineItems.Quantity, LineItems.Description
FROM Orders INNER JOIN LineItems ON Orders.OrderID = LineItems.OrderID
WHERELineItems.LineItemID = (SELECT MIN(LineItemID) FROM LineItemsWHERE OrderID = Orders.OrderID)
这需要对一个索引(或主键) LineItems.LineItemID
和索引LineItems.OrderID
或这将是缓慢的。
#5楼
编辑:没关系,夸斯诺伊有一个更好的答案。
对于SQL2K,如下所示:
SELECT Orders.OrderNumber
, LineItems.Quantity
, LineItems.Description
FROM ( SELECT Orders.OrderID, Orders.OrderNumber, FirstLineItemID = (SELECT TOP 1 LineItemIDFROM LineItemsWHERE LineItems.OrderID = Orders.OrderIDORDER BY LineItemID -- or whatever else)FROM Orders) Orders
JOIN LineItems ON LineItems.OrderID = Orders.OrderID AND LineItems.LineItemID = Orders.FirstLineItemID
#6楼
@Quassnoi的答案很好,在某些情况下(特别是如果外部表很大),使用窗口函数可能是更有效的查询,如下所示:
SELECT Orders.OrderNumber, LineItems2.Quantity, LineItems2.Description
FROM Orders
LEFT JOIN (SELECT LineItems.Quantity, LineItems.Description, OrderId, ROW_NUMBER()OVER (PARTITION BY OrderId ORDER BY (SELECT NULL)) AS RowNumFROM LineItems) LineItems2 ON LineItems2.OrderId = Orders.OrderID And RowNum = 1
有时您只需要测试哪个查询可以提供更好的性能。
#7楼
我通过使用LEFT JOIN和GROUP BY Orders.OrderNumber解决了类似的问题。 有没有理由不这样做呢?
SELECT Orders.OrderNumber, LineItems.Quantity, LineItems.Description
FROM OrdersLEFT JOIN LineItems ON Orders.OrderID = LineItems.OrderID
GROUP BY Orders.OrderNumber
我将用您自己的问题的答案回答您的回答问题:
Orders LineItems
+-------------+ +---------+----------+---------------+
| OrderNumber | | OrderID | Quantity | Description |
+-------------+ +---------+----------+---------------+
| 22586 | | 22586 | 17 | Trunion |
+-------------+ | 22586 | 3 | Girdle Spring |+---------+----------+---------------+
将两者在OrderNumber上结合在一起可以得到:
OrderNumber Quantity Description
----------- -------- -------------
22586 17 Trunion
22586 3 Girdle Spring2 row(s) affected
我们希望它只返回一行的地方:
OrderNumber Quantity Description
----------- -------- -------------
22586 17 Trunion1 row(s) affected
这就是为什么我使用GROUP BY Orders.OrderNumber的原因,每个OrderNumber只返回一行。
#8楼
关联子查询是依赖于外部查询的子查询。 就像SQL中的for循环一样。 子查询将为外部查询中的每一行运行一次:
select * from users join widgets on widgets.id = (select id from widgetswhere widgets.user_id = users.idorder by created_at desclimit 1
)
#9楼
我最喜欢的运行此查询的方式是使用不存在子句。 我相信这是运行这种查询的最有效方法:
select o.OrderNumber,li.Quantity,li.Description
from Orders as o
inner join LineItems as li
on li.OrderID = o.OrderID
where not exists (select 1from LineItems as li_laterwhere li_later.OrderID = o.OrderIDand li_later.LineItemGUID > li.LineItemGUID)
但是我没有针对这里建议的其他方法测试过这种方法。
#10楼
,使用通用表表达式的另一个方法:
with firstOnly as (select Orders.OrderNumber, LineItems.Quantity, LineItems.Description, ROW_NUMBER() over (partiton by Orders.OrderID order by Orders.OrderID) lpFROM Ordersjoin LineItems on Orders.OrderID = LineItems.OrderID
) select *from firstOnlywhere lp = 1
或者,最后您是否想显示所有连接的行?
逗号分隔版本:
select *from Orders ocross apply (select CAST((select l.Description + ','from LineItems lwhere l.OrderID = s.OrderIDfor xml path('')) as nvarchar(max)) l) lines
#11楼
从SQL Server 2012起,我认为这可以解决问题:
SELECT DISTINCTo.OrderNumber ,FIRST_VALUE(li.Quantity) OVER ( PARTITION BY o.OrderNumber ORDER BY li.Description ) AS Quantity ,FIRST_VALUE(li.Description) OVER ( PARTITION BY o.OrderNumber ORDER BY li.Description ) AS Description
FROM Orders AS oINNER JOIN LineItems AS li ON o.OrderID = li.OrderID
SQL Server:如何加入第一行相关推荐
- SQL Server死锁诊断--同一行数据在不同索引操作下引起的死锁
死锁概述 对于数据库中出现的死锁,通俗地解释就是:不同Session(会话)持有一部分资源,并且同时相互排他性地申请对方持有的资源,然后双方都得不到自己想要的资源,从而造成的一种僵持的现象. 当然,在 ...
- SQL Server 索引结构及其使用(二)(转)
SQL Server 索引结构及其使用(二) 作者:freedk 一.深入浅出理解索引结构 改善SQL语句 很多人不知道SQL语句在SQL SERVER中是如何执行的,他们担心自己所写的SQL语句会被 ...
- 【翻译】SQL Server索引进阶:第三级,聚集索引
原文地址: Stairway to SQL Server Indexes: Level 3, Clustered Indexes 本文是SQL Server索引进阶系列(Stairway to SQL ...
- SQL Server 索引结构及其使用(二)
作者:freedk 一.深入浅出理解索引结构 改善SQL语句 很多人不知道SQL语句在SQL SERVER中是如何执行的,他们担心自己所写的SQL语句会被SQL SERVER误解.比如: select ...
- 一篇绝好的讲sql server索引的文章,值得收藏
1.文章实验所使用的表结构 CREATE TABLE [dbo].[TGongwen] ( --TGongwen是红头文件表名 [Gid] [int] IDENTITY (1, 1) NOT NULL ...
- 十步优化SQL Server中的数据访问
故事开篇:你和你的团队经过不懈努力,终于使网站成功上线,刚开始时,注册用户较少,网站性能表现不错,但随着注册用户的增多,访问速度开始变慢,一些用户开始发来邮件表示抗议,事情变得越来越糟,为了留住用户, ...
- SQL Server中的SQL语句优化与效率问题
很多人不知道SQL语句在SQL SERVER中是如何执行的,他们担心自己所写的SQL语句会被SQL SERVER误解.比如: select * from table1 where name='zhan ...
- SQL Server聚集索引的选择
先声明文章非原创,摘自博客园:http://www.cnblogs.com/CareySon/archive/2012/03/06/2381582.html 简介 在SQL Server中,数据 ...
- 【转】SQL Server 索引结构及其使用(二)
SQL Server 索引结构及其使用(二) 作者:freedk 一.深入浅出理解索引结构 改善SQL语句 很多人不知道SQL语句在SQL SERVER中是如何执行的,他们担心自己所写的SQL语句会 ...
- SQL Server的聚集索引和非聚集索引
微软的SQL SERVER提供了两种索引:聚集索引(clustered index,也称聚类索引.簇集索引)和非聚集索引(nonclustered index,也称非聚类索引.非簇集索引)-- (一) ...
最新文章
- 教你用10行Python代码实现目标检测(附代码)
- 掩码计算工具netmask
- JavaFx 实用小工具超 60+ 大集合
- 关于MySQL查询优化 の 30条忠告
- 【WPF】右键菜单ContextMenu可点击区域太小的问题
- ActivityInfo taskAffinity
- python中knn_如何在python中从头开始构建knn
- Hive数据如何同步到MaxCompute之实践讲解
- ef执行原生sql语句_EF Core中执行原生SQL语句
- linux指令 sed,Linux命令sed
- db h2 数据类型_H2数据库函数及数据类型概述
- type与instance区别
- 网络人“时间都去哪儿了”
- 老罗Android开发视频教程 15集
- 应用java编写 按键小脚本_一个使用JAVA编写的类似按键精灵的程序,支持脚本文件编写(含源代码) | 学步园...
- 魔方——一面两层之后的公式
- 解剖热敏打印原理—热敏打印机真的没墨水了吗?
- php tracert,详解路由跟踪命令(tracert)
- OSError: [WinError 1455] 页面文件太小,无法完成操作。 Error loading “D:\Anaconda\envs\pytorch-1.4\lib\site-package
- ideaij 按内容查找文件