简体   繁体   English

SQL Server:联接上的子查询

[英]SQL Server: Subquery on a join

I have two tables with schema and data as below. 我有两个具有架构和数据的表,如下所示。 Table A has an id and an associated name . 表A具有一个id和一个关联的name Table B associates the id from Table A with a price and otherAttr . 表B相关联的idTable ApriceotherAttr For each entry in Table A, there may be multiple entries with different prices in Table B, but otherAttr is the same for each entry. 对于表A中的每个条目,表B中可能有多个价格不同的条目,但是otherAttr对于每个条目都是相同的。

Given an id for Table A, I would like to select the name , otherAttr , and the minimum price . 给定表A的id ,我想选择nameotherAttr和最低price

The below query returns multiple results, I need to write a query that will return a single result with the minimum price. 下面的查询返回多个结果,我需要编写一个查询,该查询将以最低价格返回单个结果。

SELECT a.name, b.price, b.otherAttr 
FROM A a
LEFT Join B b on b.idFromA = 1
WHERE a.id = 1


    Table A        Table B 
    id | name      idFromA | price | otherAttr
    --------       ---------------------------
    1 | A          1       | 200   | abc
    2 | B          1       | 300   | abc
                   1       | 400   | abc
                   2       | 20    | def
                   2       | 30    | def
                   2       | 40    | ef

I massively oversimplified my example. 我大大简化了我的榜样。 In addition to selecting the min price and otherAttr from Table B, I also have to select a bunch of other attributes from joins on other tables. 除了从表B中选择最低价格和otherAttr,我还必须从其他表的联接中选择一堆其他属性。 Which is why I was thinking the Group By and Min should be a subquery of the join on Table B, as a way to avoid Grouping By all the attributes I am selecting (because the attributes being selected for vary programmatically). 这就是为什么我认为Group By和Min应该是表B上联接的子查询,这是一种避免按我选择的所有属性进行分组的方法(因为按编程方式选择了这些属性)。

The Actual query looks more like: 实际查询看起来更像:

SELECT a.name, b.price, b.otherAttr, c.x, c.y, d.e, d.f, g.h....
FROM A a
LEFT Join B b on b.idFromA = 1
LEFT Join C c on something...
LEFT Join D d on something...
LEFT Join G g on something...

WHERE a.id = 1

To get this, you could use GROUP BY in an INNER query: 为此,您可以在INNER查询中使用GROUP BY:

SELECT gd.name, gd.price,gd.otherAttr, c.x, c.y, d.e, d.f, g.h....
FROM 
(SELECT a.id,a.name, MIN(b.price) as price, b.otherAttr 
FROM A a
LEFT Join B b on b.idFromA = 1
WHERE a.id = 1
GROUP BY a.id,a.name,b.otherAttr) gd
LEFT Join B b on b.idFromA = 1
LEFT Join C c on something...
LEFT Join D d on something...
LEFT Join G g on something...

Try:- 尝试:-

SELECT a.name, MIN(b.price) minprice, b.otherAttr 
FROM A a
LEFT Join B b ON a.Id = b.idFromA
GROUP BY a.name, b.otherAttr
HAVING a.id = 1

You could just do this instead: 您可以改为这样做:

SELECT a.name, MIN(b.price), MIN(b.otherAttr) 
FROM TableA a
LEFT JOIN TableB b on b.idFromA = a.id
GROUP BY a.name
HAVING a.id = 1;

You need to inner join on price as well in addition to id on the subquery to intersect the right record(s) with the lowest price(s). 除了子查询上的id外,还需要在价格上进行内部联接,以使价格最低的正确记录相交。 Then TOP(1) will return only one of those records. 然后,TOP(1)将仅返回这些记录之一。 You can avoid using TOP(1) if you can expand the conditions and group by fields in the subquery so you schema can assure only a single record is returned for that combination of attributes. 如果可以扩展条件并在子查询中按字段分组,则可以避免使用TOP(1),这样您的架构可以确保对于该属性组合仅返回单个记录。 Lastly, avoid left joins when intersecting sets. 最后,在相交集合时避免左连接。

SELECT TOP(1) p.id, p.price, b.OtherAttr
FROM B as b
INNER JOIN
    (SELECT A.id, min(B.price) as price
     FROM B
     INNER JOIN A on A.id=B.idFromA and A.ID=1
     GROUP BY A.id) as p on b.idFromA=p.id and b.price=p.price

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM