如何将前1个字段正确连接到SQL查询

如何将前1个字段正确连接到SQL查询,sql,sql-server,tsql,sql-server-2012,Sql,Sql Server,Tsql,Sql Server 2012,如何将注释块中的字段正确地连接到SQL查询?我在订单头上有一个计费电话号码,但在订单行上,每行都有一个发货电话号码。账单和运输可以不同 在一个订单的每一个订单行上,99%的发货数量相同,但我想做前1名,而不是分组,以防一些数据弄乱 我认为UNION可能会满足我的需求,但似乎有更好的方法可以在一个查询中获取所有内容,而不是复制和粘贴相同的where子句 SELECT a.Order_no ,a.Customer_no ,a.BILL_LAST_NAME ,

如何将注释块中的字段正确地连接到SQL查询?我在订单头上有一个计费电话号码,但在订单行上,每行都有一个发货电话号码。账单和运输可以不同

在一个订单的每一个订单行上,99%的发货数量相同,但我想做前1名,而不是分组,以防一些数据弄乱

我认为UNION可能会满足我的需求,但似乎有更好的方法可以在一个查询中获取所有内容,而不是复制和粘贴相同的where子句

SELECT a.Order_no
       ,a.Customer_no
       ,a.BILL_LAST_NAME
       ,a.BILL_FIRST_NAME
       ,b.email
       ,a.BILL_ADDRESS1
       ,a.BILL_ADDRESS2
       ,a.BILL_CITY
       ,a.BILL_STATE
       ,a.BILL_POSTAL_CODE
       ,a.BILL_COUNTRY
       ,b.Address_Type
       ,a.BILL_PHONE
       ,a.BILL_PHONE_EXT
       ,a.Order_Date
       ,a.billing_status
       ,a.PO_Number
       ,a.Customer_comments
       ,a.ShipMethodShipperDesc
       ,a.ShipRate
       ,a.CouponDiscountCode
       ,a.CouponDiscount
       ,a.CustomerDiscount
       ,a.CustomerDiscountPercent
       ,a.SalesTaxTotal
       ,a.Payment_Method
       ,a.Credit_Card_Type
       ,a.Credit_Card_Number
       ,a.Order_Date
       ,a.BILL_TYPE
       ,a.Order_Net
       /* I added these lines but would like them joined properly */
       /*-------->*/
       , (select top 1 SHIP_ADDRESS1 from LineItems C where c.ORDER_NO = a.ORDER_NO)
       , (select top 1 SHIP_ADDRESS2  from LineItems C where c.ORDER_NO = a.ORDER_NO)
       , (select top 1 SHIP_CITY from LineItems C where c.ORDER_NO = a.ORDER_NO)
       , (select top 1 SHIP_STATE from LineItems C where c.ORDER_NO = a.ORDER_NO)
       , (select top 1 SHIP_POSTAL_CODE from LineItems C where c.ORDER_NO = a.ORDER_NO)
       , (select top 1 SHIP_COUNTRY from LineItems C where c.ORDER_NO = a.ORDER_NO)
       /*<-----------*/
FROM Orders AS a
       ,Customers AS b
WHERE a.customer_no = b.customer_no
       AND a.AccountName = 'mywebaccount'
       AND a.billing_status <> 'Canceled'
       AND a.transferred = 0
       AND a.order_status <> 'Canceled'
       AND EXISTS (
              SELECT *
              FROM LineItems c
              WHERE c.order_no = a.order_no
              )
ORDER BY a.order_date
       ,a.order_no
首先,不要从一些表1做t1,一些表2做t2。始终显式联接。其次,从您的案例外观来看,APPLY的一些变体非常适合

以下是我的版本:

SELECT a.Order_no
      ,a.Customer_no
      ,a.BILL_LAST_NAME
      ,a.BILL_FIRST_NAME
      ,b.email
      ,a.BILL_ADDRESS1
      ,a.BILL_ADDRESS2
      ,a.BILL_CITY
      ,a.BILL_STATE
      ,a.BILL_POSTAL_CODE
      ,a.BILL_COUNTRY
      ,b.Address_Type
      ,a.BILL_PHONE
      ,a.BILL_PHONE_EXT
      ,a.Order_Date
      ,a.billing_status
      ,a.PO_Number
      ,a.Customer_comments
      ,a.ShipMethodShipperDesc
      ,a.ShipRate
      ,a.CouponDiscountCode
      ,a.CouponDiscount
      ,a.CustomerDiscount
      ,a.CustomerDiscountPercent
      ,a.SalesTaxTotal
      ,a.Payment_Method
      ,a.Credit_Card_Type
      ,a.Credit_Card_Number
      ,a.Order_Date
      ,a.BILL_TYPE
      ,a.Order_Net
      ,li.SHIP_ADDRESS1
      ,li.SHIP_ADDRESS2
      ,li.SHIP_CITY
      ,li.SHIP_STATE
      ,li.SHIP_POSTAL_CODE
      ,li.SHIP_COUNTRY
FROM Orders AS a
INNER JOIN Customers AS b
    ON a.customer_no = b.customer_no
CROSS APPLY
(
    SELECT TOP 1 c.SHIP_ADDRESS1
                ,c.SHIP_ADDRESS2
                ,c.SHIP_CITY
                ,c.SHIP_STATE
                ,c.SHIP_POSTAL_CODE
                ,c.SHIP_COUNTRY 
    FROM LineItems c
    WHERE c.ORDER_NO = a.ORDER_NO
    ORDER BY c.Id -- or whatever
) AS li
WHERE a.AccountName = 'mywebaccount'
AND a.billing_status <> 'Canceled'
AND a.transferred = 0
AND a.order_status <> 'Canceled'
-- no need for that exists since CROSS APPLY works like INNER JOIN
ORDER BY a.order_date,a.order_no

我建议如下:

SELECT Order_no
       ,Customer_no
       ,BILL_LAST_NAME
       ,BILL_FIRST_NAME
       ... 
       ,SHIP_ADDRESS1
       ,SHIP_ADDRESS2
       ,SHIP_CITY
       ,SHIP_STATE
       ,SHIP_POSTAL_CODE
       ,SHIP_COUNTRY
FROM (

SELECT a.Order_no
       ,a.Customer_no
       ,a.BILL_LAST_NAME
       ,a.BILL_FIRST_NAME
       ,b.email
       ,a.BILL_ADDRESS1
       ,a.BILL_ADDRESS2
       ,a.BILL_CITY
       ,a.BILL_STATE
       ,a.BILL_POSTAL_CODE
       ,a.BILL_COUNTRY
       ,b.Address_Type
       ,a.BILL_PHONE
       ,a.BILL_PHONE_EXT
       ,a.Order_Date
       ,a.billing_status
       ,a.PO_Number
       ,a.Customer_comments
       ,a.ShipMethodShipperDesc
       ,a.ShipRate
       ,a.CouponDiscountCode
       ,a.CouponDiscount
       ,a.CustomerDiscount
       ,a.CustomerDiscountPercent
       ,a.SalesTaxTotal
       ,a.Payment_Method
       ,a.Credit_Card_Type
       ,a.Credit_Card_Number
       ,a.Order_Date
       ,a.BILL_TYPE
       ,a.Order_Net
       ,c.SHIP_ADDRESS1
       ,c.SHIP_ADDRESS2
       ,c.SHIP_CITY
       ,c.SHIP_STATE
       ,c.SHIP_POSTAL_CODE
       ,c.SHIP_COUNTRY
       , row_number() over (partition by a.order_no
                            order by SHIP_ADDRESS1, SHIP_ADDRESS2, SHIP_CITY, SHIP_STATE
                                   , SHIP_POSTAL_CODE, SHIP_COUNTRY) as rn
FROM Orders AS a
JOIN Customers AS b
    ON a.customer_no = b.customer_no
JOIN numberLineItems c
    ON c.order_no = a.order_no
WHERE a.AccountName = 'mywebaccount'
       AND a.billing_status <> 'Canceled'
       AND a.transferred = 0
       AND a.order_status <> 'Canceled'
) as x
WHERE rn = 1
ORDER BY order_date
       , order_no;

我创建了一个简单的示例并发布了

最简单的方法就是从子查询中与前1联接

select cus.*, ord.*, sub.*
from Customer cus
join [Order] ord on ord.CustomerId = cus.Id
join (
  select it.OrderId, it.ItemName, it.ItemAddress
  from Items it
  where it.Id in (select MAX(id) from Items group by OrderId)
  ) as sub on sub.OrderId = ord.Id 
如果要查看第一项而不是最后一项,可以将MAXid替换为MINid

请注意,唯一的问题是,如果订单中没有项目,它将不会显示。 但是,如果您收到的订单中没有项目,但仍然希望显示该项目,则可以使用左连接

用小提琴演奏一个跑步的例子


我希望您不介意我使用显式连接=

您可以使用子查询进行连接,在子查询中可以将其放在顶部。顺便说一句,很长一段时间我没有看到隐式连接我如何用子查询连接多个字段?您只连接订单号并检索多个列。但是,是的,您可以在join中使用任何布尔谓词。我将查询的最后一部分更改为此,但它不起作用。但是我觉得我很接近:从订单a内部连接客户b在b上。客户号=a。客户号无内部连接从c上的行项目c中选择前1个订单号,发货地址1,发货地址2,发货城市,发货州,发货邮政编码,发货国家。订单号=a。订单号看起来比原来的好多了。当然,当使用TOP时,我们还需要有一个order by。@SeanLange是的,当我更担心得到不可靠的缩进而不是完成查询时,就会发生这种情况。已编辑。交叉应用是否比使用分区更好?我最终使用了分区method@user1387756我认为在速度方面也差不多。就风格而言,我更喜欢我的方法,因为我发现它更具可读性,应用是做你需要的事情的正确方法。不幸的是,我没有可靠的Id。你真的不需要Id,你可以得到任意项,在子查询中有很多方法可以得到它:交叉应用、分区、哈希、行数等等