SQL Server - 条件LEFT JOIN,双方都有条件

时间:2018-04-04 07:51:02

标签: sql sql-server left-join case sql-server-2014

我正在尝试使用条件连接执行SELECT查询,但是在连接的两边都有条件,因为根据条件是否满足,然后加入的表和列将是不同的。这是我正在尝试的查询:

plot_stats_freq_continu <- function(df,  Var , y = NAP)
{

  df$sinistres <- rep(1,nrow(df))
  data_graph <- df %>% 
    group_by(!! Var)%>%
    summarise(Annee_police = sum(NAP), Nb_sinistres= sum(sinistres)) %>%  
    mutate(Fréquence = mean((Nb_sinistres/Annee_police)))     

  ndata_graph <-  as.data.frame(data_graph)
  p <- ggplot(data=data_graph, aes(x=Var)) +geom_density() +geom_point(data=data_graph, aes(x=Var, y= Fréquence))
  plot(p)
}

这是我正在使用的数据:

邮编:

SELECT   per.Name, post.Category 
FROM     Person per
         LEFT JOIN WorkAddress wa ON per.WorkAddressID = wa.ID
         LEFT JOIN HomeAddress ha ON per.ID = ha.PersonID
         LEFT JOIN Postcode post ON 
         (CASE   WHEN per.WorkAddressID IS NOT NULL THEN wa.PostCodeID ELSE ha.PostCode+ha.Suburb END) =
         (CASE WHEN per.WorkAddressID IS NOT NULL THEN post.ID ELSE post.PostcodeSuburb END)

招聘人数:

[ID] INT IDENTITY (1,1) NOT NULL CONSTRAINT [PK_Postcode] PRIMARY KEY,
[Postcode] VARCHAR(4) NOT NULL,
[PostcodeSuburb] VARCHAR(100) NOT NULL,
[Category] INT NOT NULL

+----+----------+----------------+----------+
| ID | Postcode | PostcodeSuburb | Category |
+----+----------+----------------+----------+
|  1 |     1000 | 1000CityA      |        1 |
|  2 |     2000 | 2000CityB      |        2 |
+----+----------+----------------+----------+

人:

[ID] INT IDENTITY (1,1) NOT NULL CONSTRAINT [PK_WorkAddress] PRIMARY KEY,
[Name] VARCHAR(50) NOT NULL,
[Address] VARCHAR(100) NOT NULL,
[PostCodeID] INT NOT NULL CONSTRAINT [FK_WorkAddress_PostCodeID] FOREIGN KEY REFERENCES Postcode(ID)

+----+-----------------+---------------+------------+
| ID |      Name       |    Address    | PostcodeID |
+----+-----------------+---------------+------------+
|  1 | CityA Town Hall | 10 Main Road  |          1 |
|  2 | CityB Palace    | 1 Palace Lane |          2 |
+----+-----------------+---------------+------------+

是homeAddress:

[ID] INT IDENTITY (1,1) NOT NULL CONSTRAINT [PK_Person] PRIMARY KEY,
[Name] VARCHAR(50) NOT NULL,
[WorkAddressID] INT NULL CONSTRAINT [FK_Person_WorkAddressID] FOREIGN KEY REFERENCES WorkAddress(ID)

+----+---------------+---------------+
| ID |     Name      | WorkAddressID |
+----+---------------+---------------+
|  1 | Johnny Smiles | 1             |
|  2 | Granny Smith  | NULL          |
|  3 | Smithee Black | 2             |
+----+---------------+---------------+

目前我收到错误[ID] INT IDENTITY (1,1) NOT NULL CONSTRAINT [PK_HomeAddress] PRIMARY KEY, [PersonID] INT NOT NULL CONSTRAINT [FK_HomeAddress_PersonID] FOREIGN KEY REFERENCES Person(ID), [Address] VARCHAR(100) NOT NULL, [PostCode] VARCHAR(4) NOT NULL, [Suburb] VARCHAR(50) NOT NULL +----+----------+----------------+----------+--------+ | ID | PersonID | Address | PostCode | Suburb | +----+----------+----------------+----------+--------+ | 1 | 1 | 3 Little Road | 1000 | CityA | | 2 | 2 | 80 Main Road | 1000 | CityA | | 3 | 3 | 6 Village Lane | 2000 | CityB | +----+----------+----------------+----------+--------+ 尽管在两个CASE语句中都使用了相同的条件。我想知道是否实际上可以完全使用CASE语句,或者我是否需要使用不同的方法,因为如果只有一方有CASE语句而不是两者都有条件JOIN与CASE一起工作。

不,我不想完全改变桌面结构。

SQL小提琴:http://www.sqlfiddle.com/#!18/56485/4

2 个答案:

答案 0 :(得分:3)

我相信您只需要将<a data-rel="back" data-direction="reverse" href="#" class="ui-btn-text ui-btn-inline btn-back" title="Go back"><span class="pe-7s-angle-left"></span></a> 转换为int

varchar

sqlfiddle

在这种情况下,问题似乎是由于SQL Server始终执行从varchar到int的隐式转换(如果比较int和varchar)。您可以使用以下示例进行尝试:

SELECT    per.Name, post.Category 
FROM      Person per
          LEFT JOIN WorkAddress wa ON per.WorkAddressID = wa.ID
          LEFT JOIN HomeAddress ha ON per.ID = ha.PersonID
          LEFT JOIN Postcode post ON 
          (CASE WHEN per.WorkAddressID IS NOT NULL THEN CAST(wa.PostCodeID AS varchar(100)) ELSE ha.PostCode+ha.Suburb END) =
          (CASE WHEN per.WorkAddressID IS NOT NULL THEN CAST(post.ID AS varchar(100)) ELSE post.PostcodeSuburb END)

dbfiddle

编辑:正如@dnoeth所提到的,-- #1 example with data as ( select 10 a, '10' b ) select * from data where a = b; -- #2 example with data as ( select 10 a, 'b' b ) select * from data where a = b; 要求所有返回路径返回相同的数据类型,因此SQL Server会因CASE优先级进行varchar转换(如图所示)在上面的例子中。)

答案 1 :(得分:1)

我建议不要在case子句中使用on。只需使用布尔逻辑:

ON (per.WorkAddressID IS NOT NULL AND wa.PostCodeID = post.ID) OR
   (per.WorkAddressID IS NULL AND ha.PostCode + ha.Suburb post.PostcodeSuburb)

这假设类型与第二次比较兼容。如果不是,请使用CONCAT()或将其明确转换为字符串。