【问题标题】:SQL query is showing error with more than one join on same tableSQL 查询在同一个表上显示多个联接的错误
【发布时间】:2017-09-23 19:37:16
【问题描述】:

我在 StackOverflow 和互联网上进行了搜索,但没有找到任何解决此问题的方法。 我在 SQL Server 2008 R2 中有一个类似于 myTable 的表,其中包含以下列: person_id,city,addressType,line_num,textarea 和其他一些列,但这些不是必需的。 所有字段都是 int 类型,但 textarea 是 varchar(10) 类型。 一个人在一个城市中可以有多种类型的地址。地址可以很大,因此每个地址类型可以有多个行号。地址类型 1 是家庭地址,地址类型 2 是办公室地址,地址类型 3 是其他地址。 这里给出了示例行

person_id|city|addressType|line_num|textarea
1        |1   |1          |0       |House no.
---------------------------------------------
1        |1   |1          |1       |10
---------------------------------------------
1        |1   |2          |0       |Building5
---------------------------------------------
1        |1   |2          |1       |Floor 1
---------------------------------------------
1        |1   |3          |0       |Factory
---------------------------------------------
1        |1   |3          |1       |no. 30

我需要在一行中显示一个人的所有类型的地址。像这样:

person_id|city|homeAddress |officeAddress    |otherAddress
1        |1   |House no.,10|Building5,Floor 1|Factory,no.30

我使用了加入。 连接适用于地址类型 1 和地址类型 2。

这是一个运行良好的单连接查询:

SET ANSI_PADDING ON;
SELECT DISTINCT homeAddress_person_id, homeAddress_city, homeAddress, officeAddress
FROM
/*Sub query for home address*/
(SELECT person_id AS homeAddress_person_id, city AS homeAddress_city,
/*Concatinating home address*/
STUFF((SELECT ',' + textarea FROM myTable WHERE person_id=ResultsFrom_myTable_For_homeAddress.person_id AND city=ResultsFrom_myTable_For_homeAddress.city AND addressType=ResultsFrom_myTable_For_homeAddress.addressType FOR XML PATH(''),TYPE).value('.','VARCHAR(4000)'),1,1,'') AS homeAddress
FROM myTable ResultsFrom_myTable_For_homeAddress WHERE person_id=1 AND addressType=1
GROUP BY person_id,city,addressType) ResultsFrom_myTable_For_homeAddress_outer

FULL OUTER JOIN
/*Sub query for office address*/
(SELECT person_id AS officeAddress_person_id, city AS officeAddress_city,
/*Concatinating office address*/
STUFF((SELECT ',' + textarea FROM myTable WHERE person_id=ResultsFrom_myTable_For_officeAddress.person_id AND city=ResultsFrom_myTable_For_officeAddress.city AND addressType=ResultsFrom_myTable_For_officeAddress.addressType FOR XML PATH(''),TYPE).value('.','VARCHAR(4000)')
,1
,1
,'') AS officeAddress
FROM myTable ResultsFrom_myTable_For_officeAddress
WHERE person_id=1 AND addressType=2
GROUP BY person_id,city,addressType) ResultsFrom_myTable_For_officeAddress_outer
ON ResultsFrom_myTable_For_homeAddress_outer.homeAddress_person_id=ResultsFrom_myTable_For_officeAddress_outer.officeAddress_person_id AND ResultsFrom_myTable_For_homeAddress_outer.homeAddress_city=ResultsFrom_myTable_For_officeAddress_outer.officeAddress_city
SET ANSI_PADDING OFF;

但是当我添加另一个连接以显示其他地址时。它显示错误在预期条件的上下文中指定的非布尔类型的表达式 这是有两个连接的查询

SET ANSI_PADDING ON;
SELECT DISTINCT homeAddress_person_id, homeAddress_city, homeAddress, officeAddress, otherAddress
FROM
/*Sub query for home address*/
(SELECT person_id AS homeAddress_person_id, city AS homeAddress_city,
/*Concatinating home address*/
STUFF((SELECT ',' + textarea FROM myTable WHERE person_id=ResultsFrom_myTable_For_homeAddress.person_id AND city=ResultsFrom_myTable_For_homeAddress.city AND addressType=ResultsFrom_myTable_For_homeAddress.addressType FOR XML PATH(''),TYPE).value('.','VARCHAR(4000)'),1,1,'') AS homeAddress
FROM myTable ResultsFrom_myTable_For_homeAddress WHERE person_id=1 AND addressType=1
GROUP BY person_id,city,addressType) ResultsFrom_myTable_For_homeAddress_outer

FULL OUTER JOIN
/*Sub query for office address*/
(SELECT person_id AS officeAddress_person_id, city AS officeAddress_city,
/*Concatinating office address*/
STUFF((SELECT ',' + textarea FROM myTable WHERE person_id=ResultsFrom_myTable_For_officeAddress.person_id AND city=ResultsFrom_myTable_For_officeAddress.city AND addressType=ResultsFrom_myTable_For_officeAddress.addressType FOR XML PATH(''),TYPE).value('.','VARCHAR(4000)')
,1
,1
,'') AS officeAddress
FROM myTable ResultsFrom_myTable_For_officeAddress
WHERE person_id=1 AND addressType=2
GROUP BY person_id,city,addressType) ResultsFrom_myTable_For_officeAddress_outer
ON ResultsFrom_myTable_For_homeAddress_outer.homeAddress_person_id=ResultsFrom_myTable_For_officeAddress_outer.officeAddress_person_id AND ResultsFrom_myTable_For_homeAddress_outer.homeAddress_city=ResultsFrom_myTable_For_officeAddress_outer.officeAddress_city

FULL OUTER JOIN
/*Sub query for other address*/
(SELECT person_id AS otherAddress_person_id,city AS otherAddress_city,
/*Concatinating office address*/
STUFF((SELECT ',' + textarea FROM myTable WHERE person_id=ResultsFrom_myTable_For_otherAddress.person_id AND city=ResultsFrom_myTable_For_otherAddress.city AND addressType=ResultsFrom_myTable_For_otherAddress.addressType FOR XML PATH(''),TYPE).value('.','VARCHAR(4000)'),1,1,'') AS otherAddress
FROM myTable ResultsFrom_myTable_For_otherAddress WHERE person_id=1 AND addressType=3
GROUP BY person_id,city,addressType) ResultsFrom_myTable_For_otherAddress_outer
ON ResultsFrom_myTable_For_homeAddress_outer.homeAddress_person_id=ResultsFrom_myTable_For_otherAddress_outer.otherAddress_person_id AND ResultsFrom_myTable_For_homeAddress_outer.homeAddress_city=ResultsFrom_myTable_For_otherAddress_outer.otherAddress_city;
SET ANSI_PADDING OFF;

上面的查询有什么问题?

【问题讨论】:

  • 格式化您的查询,以便更好地阅读
  • @Jens 查询已格式化。这现在更具可读性了吗?

标签: sql sql-server-2008 join


【解决方案1】:

使用common table expression 和条件聚合,我们可以清理这个查询并将其变成这样:

with cte as (
  select
      person_id
    , city
    , addressType
    , address = stuff((
        select ',' + i.textarea
        from myTable i
        where i.person_id = t.person_id
          and i.city = t.city
          and i.addressType = t.addressType
        order by line_num
      for xml path(''), type).value('.', 'varchar(4000)'), 1, 1, '')
from MyTable as t
group by person_id, city, addressType
)
select
    t.person_id
  , t.city
  , homeAddress   = max(case when t.addressType = 1 then t.address end)
  , officeAddress = max(case when t.addressType = 2 then t.address end)
  , otherAddress  = max(case when t.addressType = 3 then t.address end)
from cte as t
where t.person_id = 1
group by t.person_id, t.city

rextester 演示:http://rextester.com/RWIQ34896

返回:

+-----------+------+--------------+-------------------+----------------+
| person_id | city | homeAddress  |   officeAddress   |  otherAddress  |
+-----------+------+--------------+-------------------+----------------+
|         1 |    1 | House no.,10 | Building5,Floor 1 | Factory,no. 30 |
+-----------+------+--------------+-------------------+----------------+

您的问题说addressType 0 是家,但您的查询使用addressType 1。我相信您可以对这个查询进行适当的调整。

【讨论】:

  • 谢谢。地址类型 1 是家。问题已更新。
  • 这就像魔术一样。你是救世主。我希望能给你 10 票。感谢您让我学习新事物。
  • @Varun 乐于助人!
猜你喜欢
  • 2012-08-09
  • 2018-03-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-23
  • 1970-01-01
相关资源
最近更新 更多