【问题标题】:SQL joins and inner joins and is nullSQL 连接和内部连接并且为空
【发布时间】:2017-10-26 02:54:09
【问题描述】:

DB schema diagram here

我正在尝试返回与商店 ID 1 无关的优惠券列表 我正在尝试返回优惠券 1

这是我的努力

Select c.id
from Coupon c
left join signups s on s.couponid = c.id
inner join storelist sl on sl.groupid = s.groupid
where sl,id = 1 and s.couponid is null

谢谢

【问题讨论】:

  • 我想我已经试过left join left join

标签: sql-server join inner-join


【解决方案1】:

除非您要从注册和商店列表中返回列,否则我会这样处理您的问题;只需从优惠券表中选择并使用NOT IN 过滤掉指定的商店。

SELECT c.id
FROM coupon c
WHERE c.id NOT IN (
    SELECT s.couponid 
    FROM signups s
        JOIN storelist sl ON s.groupid = sl.groupid
    WHERE sl.id = 1
)

【讨论】:

  • 这很有效,谢谢,是否可以避免内部查询?
  • 您可以根据需要将其更改为LEFTRIGHTFULL 连接,但您将需要某种连接,因为您的 ID 分布在不同的表。你有什么理由试图避免它?
  • 只是效率
【解决方案2】:

只需在 where 子句中使用“不等于”即可:

select c.id
from Coupon c
inner join signups s on s.couponid = c.id
inner join storelist sl on sl.groupid = s.groupid
where sl.id <> 1

编辑 2

因此,使用上述查询时(来自该数据的)“预期结果”是“无结果”。但是,如果您更正数据以便注册只能引用现有商店,那么当您使用where sl.id &lt;&gt; 1时,您会看到商店 2 列出


编辑 1

取自数据模型图像的数据

CREATE TABLE StoreList
    ([id] int, [groupid] int, [address] varchar(50))
;
   
INSERT INTO StoreList
    ([id], [groupid], [address])
VALUES
    (1, 3, '35 Sharkey Rd'),
    (2, 4, '56 Jim Road')
;


CREATE TABLE signups
    ([id] int, [groupid] int, [couponid] int)
;
    
INSERT INTO signups
    ([id], [groupid], [couponid])
VALUES
    (1, 1, 2),
    (2, 3, 2)
;


CREATE TABLE Coupon
    ([id] int, [name] varchar(8))
;
    
INSERT INTO Coupon
    ([id], [name])
VALUES
    (1, 'coupon 1'),
    (2, 'coupon 2')
;

select sl.id as sl_id, *
from Coupon c
inner join signups s on s.couponid = c.id
inner join storelist sl on sl.groupid = s.groupid

;

select sl.id as sl_id, *
from Coupon c
inner join signups s on s.couponid = c.id
inner join storelist sl on sl.groupid = s.groupid
where sl.id <> 1
;
GO
sl_id |编号 |姓名 |编号 |组ID |优惠券 |编号 |组ID |地址 ----: | -: | :------- | -: | ------: | --------: | -: | ------: | :------------ 1 | 2 |优惠券2 | 2 | 3 | 2 | 1 | 3 | 35夏基路 sl_id |编号 |姓名 |编号 |组ID |优惠券 |编号 |组ID |地址 ----: | -: | :--- | -: | ------: | --------: | -: | ------: | :------

dbfiddle here

从上面的证明可以看出,如果 sl.id 不等于 1,那么确实不会返回 id 为 1 的商店。

【讨论】:

  • 我希望有一个像这样的有效解决方案,但它对我不起作用,它在真实数据中返回了一长串 2 和 1
  • 如果哪里说 sl.id 不等于 1,那么列 sl.id 怎么可能是 1?抱歉,您提到的结果没有意义。你确定你输出 sl.id 吗?
  • 顺便说一下,图像上提供的表格注册数据不是指 2 号商店,这就是为什么在没有 where 子句的查询中只显示 1 个优惠券的原因。始终检查样本数据。
  • 我的目标是输出与该商店(sl)无关的优惠券。我希望查询返回优惠券 ID 1
  • 叹息。是的。如果当然是。但我拥有的唯一数据是指 store1 或不存在的商店。第一个结果没有 where 子句。第二个结果确实有一个 where 子句。 (图像中的数据示例很糟糕)。因此,当应用 where 子句时,没有结果。如果您了解数据,哪个是正确答案。 where 子句中的不等于 1 就是您所需要的。
【解决方案3】:

要发现注册表中根本没有引用的优惠券,一个简单的选择是使用“左排除连接”:

select c.*
from coupons c
left join signups s on c.couponid = s.couponid
where s.couponid IS NULL

在这里,您在注册时引用优惠券时执行联接,然后通过 where 子句排除那些匹配的行,只留下不匹配的行。

另一个选项是通过 NOT EXISTS 进行“半连接”:

select c.*
from coupons c
where NOT EXISTS (
     select NULL
     from signups s
     where c.couponid = s.couponid
     )

请注意,该子查询中的 select 子句没有被评估,它确实存在,因为语法规则要求任何 select 查询都以 select 关键字开始。正是 from 和 where 子句提供了测试 EXISTS 或 NOT EXISTS 所需的信息,因此可以使用这些“select NULL”、“select 1”或“select *”中的任何一个,这只是一个偏好问题你确实用过。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-16
    • 2021-01-31
    • 2012-03-16
    • 2018-12-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多