【问题标题】:Join Clause With a XOR Statement使用 XOR 语句连接子句
【发布时间】:2015-04-09 08:47:29
【问题描述】:

我正在执行连接,但我似乎无法使此 XOR 正常工作。

SELECT t1.COMPANY, t1.MILES,
   CASE WHEN t2.MILES IS NULL THEN t3.MILES
        ELSE t2.MILES
   END AS MILES2,
   CASE WHEN t2.MILES = t1.MILES AND t2.MILES != 9999 THEN t2.FLATRATE
        ELSE t3.RATEBASIS
   END AS RATE           
FROM TABLE1 AS t1
    LEFT JOIN TABLE2 AS t2 
        ON t1.[COMPANY] = t2.[COMPANYCODE] AND (t1.[MILES] = t2.[MILES])
    INNER JOIN (
         SELECT TOP 1 TRUCKERCODE, MILES, RATEBASIS, FLATRATE FROM TABLE2 WHERE MILES = 9999
               ) AS t3 
   ON t1.[COMPANY] = t3.[COMPANYCODE]

如果英里数相同,我需要加入 ON 子句,然后获取匹配的给定字段,否则我需要从第二个表中获取的默认数据是英里数等于 9999 的位置。现在使用那个 ON子句我得到许多额外的行,其中 MILES 等于 45,它从 TABLE2 获取数据,其中英里等于 45 和所有数据,其中英里等于 9999。我需要它来做一个或另一个,但不是两者都做。这就是我的桌子的样子

TABLE1                          TABLE2
ID COMPANY MILES ETC            ID COMPANYCODE MILES RATE
1  ILLINI  50                   1  ILLINI      50    3.2
2  ILLINI  110                  2  ILLINI      110   5.2
3  ILLINI  150                  3  ILLINI      150   2.4
4  ILLINI  200                  4  ILLINI      200   1.9
5  ILLINI  250                  5  ILLINI      9999  1.5
6  ILLINI  300                       
7  ILLINI  350
8  ILLINI  400
9  ILLINI  450
10 ILLINI  500

Desired Output
COMPANY MILES MILES2 RATE
ILLINI  50    50    3.2
ILLINI  110   110   5.2
ILLINI  150   150   2.4
ILLINI  200   200   1.9
ILLINI  250   9999  1.5
ILLINI  300   9999  1.5                    
ILLINI  350   9999  1.5
ILLINI  400   9999  1.5
ILLINI  450   9999  1.5
ILLINI  500   9999  1.5

【问题讨论】:

  • 为什么会从输出中排除,例如,ILLINI 150 150 2.4
  • @GiorgosBetsos 我刚刚提供了一个快速版本。当然,这将包含在输出中。它将总共有 10 种不同的输出。我只是举个例子。
  • 在 SQL Server 2000 中应用我的查询时是否遇到语法错误?

标签: sql join sql-server-2000 xor


【解决方案1】:

我认为这会给你你想要的:

SELECT t1.COMPANY, t1.MILES,
       CASE WHEN t2.MILES IS NULL THEN t3.MILES
            ELSE t2.MILES
       END AS MILES2,
       CASE WHEN t2.MILES IS NULL THEN t3.RATE
            ELSE t2.RATE
       END AS RATE           
FROM TABLE1 AS t1
LEFT JOIN TABLE2 AS t2 
   ON t1.[COMPANY] = t2.[COMPANYCODE] AND (t1.[MILES] = t2.[MILES])
INNER JOIN (
   SELECT TOP 1 COMPANYCODE, MILES, RATE FROM TABLE2 WHERE MILES = 9999
) AS t3 
   ON t1.[COMPANY] = t3.[COMPANYCODE]    

如果MILES 中有匹配项,则输出包含来自TABLE1TABLE2 的两条记录。否则,输出包含来自左表的记录,即TABLE1 和来自TABLE2MILES = 9999特定 记录。

请注意TOP 1 用于最后一个子查询,以防TABLE2 中存在MILES = 9999 的多个记录。

输出:

COMPANY MILES   MILES2  RATE
----------------------------
ILLINI  50      50      3,2
ILLINI  110     110     5,2
ILLINI  150     150     2,4
ILLINI  200     200     1,9
ILLINI  250     9999    1,5
ILLINI  300     9999    1,5
ILLINI  350     9999    1,5
ILLINI  400     9999    1,5
ILLINI  450     9999    1,5
ILLINI  500     9999    1,5

SQL Fiddle Demo here

【讨论】:

  • 你能解释一下第二个内部连接在做什么吗?我了解第一个 Left Join 是如何工作的。语句如何知道何时或何时不触发 Inner Join?
  • @Kyle 第二个INNER JOIN 总是被“解雇”:它将TABLE29999 记录加入到TABLE1 的每一个记录中。使用CASE,我们可以选择是否将此9999记录包含到我们的输出中。
  • 好的,SQL 没有获取 Miles 不匹配的数据。所以它得到了 50、110、150 和 200,但 250 及以上并没有从我的桌子上抢走它们。
  • @Kyle 在这种情况下,您的真实环境中存在一些您没有告诉我们的东西。根据 OP 中提供的样本数据,我的查询产生的输出与所需的相同。
  • 2000 年和 2008 年的 SQL 有何不同?
【解决方案2】:

我会基于双左连接..一次匹配,如果没有,则默认为 9999 实例

SELECT
      T1.*,
      coalesce( T2.miles, T3.miles ) as Miles2,
      coalesce( T2.rate, T3.rate ) as MileageRate
   FROM
      TABLE1 T1
         LEFT JOIN TABLE2 T2
            on T1.Company = T2.CompanyCode
           AND T1.Miles = T2.Miles
         LEFT JOIN TABLE2 T3
            on T1.Company = T3.CompanyCode
           AND T3.Miles = 9999

确认工作at this SQL Fiddle link

【讨论】:

  • 用你的,当我用我的数据库运行它时,它会返回很多 Miles2 和 MileageRate 的空值。如果里程匹配,它将打印出正确的 Miles2 和 MileageRate。
  • @Kyle,我不知道你是否在我上次编辑之前得到它......第二个左加入是加入 T3.miles,而不是 T2.miles。你能确认一下并告诉我。
  • 我使用的SQL查询和你上面的完全一样
  • @Kyle,我刚刚尝试并发布了一个指向 SQL Fiddle 的链接,该链接基于 Giorgos 提供的相同数据/架构并且没有显示 NULL 值
  • 816.0 NULL NULL 788.0 NULL NULL 1812.0 NULL NULL 0.0 NULL NULL 79.0 NULL NULL 117.0 NULL NULL 175.0 NULL NULL 798.0 NULL NULL 1230.0 NULL NULL 681.0 NULL NULL 这就是我得到的
猜你喜欢
  • 2021-11-06
  • 1970-01-01
  • 1970-01-01
  • 2017-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-09
相关资源
最近更新 更多