【问题标题】:SELECT TOP inside INNER JOINSELECT TOP inside INNER JOIN
【发布时间】:2017-02-24 17:05:22
【问题描述】:

我在 SQL Server 中创建了这个简单的数据库:

create database product_test
go

use product_test
go

create table product 
(
    id int identity primary key,
    label varchar(255),
    description text,
    price money, 
);

create table picture 
(
    id int identity primary key, 
    p_path text, 
    product int foreign key references product(id) 
); 

insert into product 
values ('flip phone 100', 'back 2 the future stuff.', 950),
       ('flip phone 200', 's;g material', 1400)

insert into picture 
values ('1.jpg', 1), ('2.jpg', 1), ('3.jpg', 2)

我想要的是为每个产品选择所有产品和只有一张图片。任何帮助是极大的赞赏。

【问题讨论】:

  • 你试过inner join (select top 1 etc from lol) img on img.whatever = outer.whatever吗?
  • 你想要哪张照片?
  • ntexttextimage 数据类型将在 SQL Server 的未来版本中删除。避免在新的开发工作中使用这些数据类型,并计划修改当前使用它们的应用程序。请改用nvarchar(max)varchar(max)varbinary(max)See details here
  • 如果产品没有图片怎么办。

标签: sql sql-server sql-server-2008 tsql sql-server-2008-r2


【解决方案1】:

为此,我是outer apply 的粉丝:

select p.*, pi.id, pi.path
from product p outer apply
     (select top 1 pi.*
      from picture pi
      where pi.product = p.id
     ) pi;

您可以包含order by 以获取一张特定图片(例如,具有最低或最高 id 的图片)。或者,order by newid() 随机获取一个。

【讨论】:

  • 嗨戈登,只是想了解你的问题,因为我从来没有为我的开发人员使用过 APPLY;在这种情况下,您获得的结果/执行计划与使用经典左联接是否相同?
  • @PaulDaubian 。 . .它应该是相似的。但是,APPLY(或更一般的横向连接)可以具有更好的性能,因为它不需要生成所有附加行号的行。如果你正在学习APPLY,可以将其视为FROM子句中的关联子查询,其优点是可以返回多列多行。
【解决方案2】:

您是否尝试过使用相关子查询?

SELECT *, (SELECT TOP 1 p_path FROM picture WHERE product = p.id ORDER BY id) 
FROM picture p

希望这会有所帮助,

【讨论】:

    【解决方案3】:
    SELECT 
    *,
    (
        SELECT TOP 1 p2.p_path
        FROM dbo.picture p2
        WHERE p.id = p2.product
    ) AS picture
    FROM dbo.product p
    

    或加入:

    SELECT 
    *
    FROM dbo.product p
    INNER JOIN 
    (
        SELECT p2.product, MIN(p2.p_path) AS p_path
        FROM dbo.picture p2
        GROUP BY p2.product
    ) AS pt
    ON p.id = pt.product
    

    但是你需要把p_path改成varchar类型

    【讨论】:

    • 这会起作用,但应该提到的是,如果 OP 想要在返回哪张图片方面保持一致,则子查询需要排序。
    • 原始问题说他想要加入。
    【解决方案4】:

    我会使用这样的窗口函数:

    SELECT *
    FROM product 
    JOIN (
      SELECT id, product, p_path, 
             row_number() OVER (PARTITION BY product ORDER BY id ASC) as RN
      FROM picture
    ) pic ON product.id = pic.product AND pic.RN = 1
    

    正如您在此处看到的,我正在选择具有最低 id (ORDER BY id ASC) 的图片——您可以根据自己的要求更改此顺序。

    【讨论】:

    • 有趣的是,如果您没有为联接提供表,您认为这将起作用
    • @Paparazzi - 哈哈,很好的收获 - 完全省略了 FROM 子句。
    【解决方案5】:

    只需分组并取最小值或最大值
    在没有图片的情况下左加入

    select pr.ID, pr.label, pr.text, pr.price
         , min(pic.p_path)
    from product pr 
    left join picture pic 
    on pic.product = pr.ID 
    group by pr.ID, pr.label, pr.text, pr.price 
    

    【讨论】:

    • 对我来说很有趣,OP 专门要求内连接(暗示他只想要带有图片的结果)你为什么建议左连接?
    • @Hogan 这在我的回答中有所提及。 "在没有图片的情况下左加入"
    • @Hogan OP 还声明想要所有产品。基于首先提出的问题,尚不清楚 OP 是否理解内部连接的含义。
    猜你喜欢
    • 1970-01-01
    • 2023-03-12
    • 2011-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多