我将使用一个具体的但假设的示例。

每个订单通常只有一个订单项

命令:

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:如何加入第一行相关推荐

  1. SQL Server死锁诊断--同一行数据在不同索引操作下引起的死锁

    死锁概述 对于数据库中出现的死锁,通俗地解释就是:不同Session(会话)持有一部分资源,并且同时相互排他性地申请对方持有的资源,然后双方都得不到自己想要的资源,从而造成的一种僵持的现象. 当然,在 ...

  2. SQL Server 索引结构及其使用(二)(转)

    SQL Server 索引结构及其使用(二) 作者:freedk 一.深入浅出理解索引结构 改善SQL语句 很多人不知道SQL语句在SQL SERVER中是如何执行的,他们担心自己所写的SQL语句会被 ...

  3. 【翻译】SQL Server索引进阶:第三级,聚集索引

    原文地址: Stairway to SQL Server Indexes: Level 3, Clustered Indexes 本文是SQL Server索引进阶系列(Stairway to SQL ...

  4. SQL Server 索引结构及其使用(二)

    作者:freedk 一.深入浅出理解索引结构 改善SQL语句 很多人不知道SQL语句在SQL SERVER中是如何执行的,他们担心自己所写的SQL语句会被SQL SERVER误解.比如: select ...

  5. 一篇绝好的讲sql server索引的文章,值得收藏

    1.文章实验所使用的表结构 CREATE TABLE [dbo].[TGongwen] ( --TGongwen是红头文件表名 [Gid] [int] IDENTITY (1, 1) NOT NULL ...

  6. 十步优化SQL Server中的数据访问

    故事开篇:你和你的团队经过不懈努力,终于使网站成功上线,刚开始时,注册用户较少,网站性能表现不错,但随着注册用户的增多,访问速度开始变慢,一些用户开始发来邮件表示抗议,事情变得越来越糟,为了留住用户, ...

  7. SQL Server中的SQL语句优化与效率问题

    很多人不知道SQL语句在SQL SERVER中是如何执行的,他们担心自己所写的SQL语句会被SQL SERVER误解.比如: select * from table1 where name='zhan ...

  8. SQL Server聚集索引的选择

    先声明文章非原创,摘自博客园:http://www.cnblogs.com/CareySon/archive/2012/03/06/2381582.html 简介    在SQL Server中,数据 ...

  9. 【转】SQL Server 索引结构及其使用(二)

    SQL Server 索引结构及其使用(二)  作者:freedk 一.深入浅出理解索引结构 改善SQL语句 很多人不知道SQL语句在SQL SERVER中是如何执行的,他们担心自己所写的SQL语句会 ...

  10. SQL Server的聚集索引和非聚集索引

    微软的SQL SERVER提供了两种索引:聚集索引(clustered index,也称聚类索引.簇集索引)和非聚集索引(nonclustered index,也称非聚类索引.非簇集索引)-- (一) ...

最新文章

  1. 教你用10行Python代码实现目标检测(附代码)
  2. 掩码计算工具netmask
  3. JavaFx 实用小工具超 60+ 大集合
  4. 关于MySQL查询优化 の 30条忠告
  5. 【WPF】右键菜单ContextMenu可点击区域太小的问题
  6. ActivityInfo taskAffinity
  7. python中knn_如何在python中从头开始构建knn
  8. Hive数据如何同步到MaxCompute之实践讲解
  9. ef执行原生sql语句_EF Core中执行原生SQL语句
  10. linux指令 sed,Linux命令sed
  11. db h2 数据类型_H2数据库函数及数据类型概述
  12. type与instance区别
  13. 网络人“时间都去哪儿了”
  14. 老罗Android开发视频教程 15集
  15. 应用java编写 按键小脚本_一个使用JAVA编写的类似按键精灵的程序,支持脚本文件编写(含源代码) | 学步园...
  16. 魔方——一面两层之后的公式
  17. 解剖热敏打印原理—热敏打印机真的没墨水了吗?
  18. php tracert,详解路由跟踪命令(tracert)
  19. OSError: [WinError 1455] 页面文件太小,无法完成操作。 Error loading “D:\Anaconda\envs\pytorch-1.4\lib\site-package
  20. ideaij 按内容查找文件

热门文章

  1. jquery submit ie6下失效的原因分析及解决方法
  2. Node——设置响应报文头实现下载
  3. Linux设备中的并发控制
  4. Android 启动多个闹钟。
  5. iOS pdf矢量图代替多倍图
  6. 【Head First Java 读书笔记】(四)对象的行为
  7. iOS8设置应用图标红点的权限问题
  8. 使用用WCF中的双工(Duplex)模式将广告图片推送到每个Winform客户端机子上
  9. logstash收集nginx日志
  10. Ubuntu 16.04 源码编译安装PHP7.2.23详细过程