【问题标题】:SQL Query Join IssueSQL 查询连接问题
【发布时间】:2014-04-15 08:48:48
【问题描述】:

我目前遇到了一个我正在尝试组合的 SQL 查询。

这是表格布局:


表一:

tblUsers 此表包含更多列,但在示例中不是必需的

  • 用户 ID(整数)

样本数据:

------
| ID |
------
| 1  |
------
| 2  |
------

表2:

tblColumns

  • 列 ID(整数)
  • 列名 (nvarchar)

样本数据:

--------------------
| ID | Column Name |
--------------------
| 1  | Name        |
--------------------
| 2  | Email       |
--------------------
| 3  | Age         |
--------------------

表 3:

tblColumnData

  • ColumnDataID (int)
  • 用户 ID (int) (FK)
  • ColumnID (int) (FK)
  • ColumnDataContent (nvarchar)

样本数据:

----------------------------------------------
| ID | UserID | ColumnID | ColumnDataContent |
----------------------------------------------
| 1  | 1      | 1        | John Smith        |
----------------------------------------------
| 2  | 1      | 2        | john@email.com    |
----------------------------------------------
| 3  | 1      | 3        | 45                |
----------------------------------------------
| 4  | 2      | 2        | james@email.com   |
----------------------------------------------
| 5  | 2      | 3        | 30                |
----------------------------------------------

您将在上面看到,UserID:2 在 tblColumnData 表中没有 ColumnID 1 的记录,即 NAME 列。即使它是 NULL,我仍然需要它出现在结果中。

所以我试图让数据像这样返回:

------------------------------------------------------
| UserID | ColumnID | ColumnName | ColumnDataContent |
------------------------------------------------------
| 1      | 1        | Name       | John Smith        |
------------------------------------------------------
| 1      | 2        | Email      | john@email.com    |
------------------------------------------------------
| 1      | 3        | Age        | 45                |
------------------------------------------------------
| 2      | 1        | Name       | NULL or ''        |
------------------------------------------------------
| 2      | 2        | Email      | james@email.com   |
------------------------------------------------------
| 2      | 3        | Age        | 30                |
------------------------------------------------------

我的选择如下所示:

 SELECT cd.UserID,c.ColumnID,c.ColumnName,cd.ColumnDataContent 
 FROM tblColumns c 
      INNER JOIN tblColumnData cd ON c.ColumnID=cd.ColumnID

我尝试了 INNER、OUTER、LEFT.... 等所有不同的连接,但没有成功。

希望有人可以提供帮助:)

谢谢

【问题讨论】:

  • 您能否将示例数据放在 sqlfiddle.com 上
  • 使用LEFT JOIN 而不是INNER JOIN
  • @Sameer:OP 提到 “我已经尝试了 INNER、OUTER、LEFT.... 等所有不同的连接,但没有成功”
  • @huMptyduMpty:我无法在 sqlfiddle 中执行此操作,因为它目前处于关闭状态。
  • @Aki: 是的,现在好像不行

标签: sql sql-server join


【解决方案1】:

我认为这会对您有所帮助:

with userCTE as (
    select
        u.userId ,
            c.columnId
    from tblUsers as u
        cross join tblColumns as c
)

select 
    u.* ,
    Coalesce(cd.ColumnDatacontent, 'N/A') AS columnDataContent
from userCTE as u
    left join tblColumnData as cd
        on u.columnId = cd.columnId and u.userID = cd.userId

您还需要选择您感兴趣的列,这只是如何获取所有需要的行的一般示例。

如果需要,您还可以使用COALESCEISNULL 函数将NULL 值转换为更具体的字符串。

【讨论】:

  • tblUsers 有 700 万条记录,“userCTE”交叉连接似乎需要很长时间。我添加了一个 WHERE 子句,它应该将 tblColumns 减少到 3 行,将 tblUsers 减少到 500。然后我应该期望返回的结果应该是 1,500 条记录,但它仍然会在表中执行所有可能的组合。在 4 秒内它返回了 120,000 条记录,此时我停止了查询 :)
  • 等等,我用另一个 WHERE 再试了一次,它成功了!谢谢!
【解决方案2】:

我认为您需要使用 CROSS JOIN。这个我没测试过,但有点像这样:

SELECT 
d.UserId
 ,d.ColumnId
,d.ColumnName
,d.ColumnDataContent
FROM tblColumns c 
CROSS JOIN tblusers u
LEFT join tblcolumndata d on d.columnid = c.columnid and d.userid = u.userid

【讨论】:

  • 我尝试了 CROSS JOIN 但查询需要永远运行。我让它运行了 25 秒,它返回了超过 180,000 条记录!
  • 您的表在 id 字段上有索引吗?如果没有,那么您将需要添加一些。
【解决方案3】:

Fiddle 倒下了,我们都瞎了眼,但如果它倒了,我会先尝试这个。

SELECT tblUsers.UserID,
       tblColumns.ColumnID,
       tblColumns.ColumnName
       tblColumnData.ColumnDataContent
  FROM tblUsers,
       tblColumns
  LEFT JOIN tblColumnData  ON tblColumnData.ColumnID = tblColumns.ColumnID
                          AND tblColumnData.UserID   = tblUsers.UserID
;

您希望用户和列的 Cartesian Product 左连接到 ColumnID 上的数据表。

【讨论】:

  • 在正常情况下,LEFT JOIN 可以解决问题,但我不知道为什么它没有。您的示例没有返回我需要的内容。
  • 是的,我错过了一个加入。已编辑以将加入添加到用户。
【解决方案4】:
select CD.UserID,CD.ColumnID,t.ColumnName,CD.ColumnDataContent
from (select distinct u.UserID,c.ID,c.[ColumnName] tblUsers u
            cross join tblColumns c)t
left join tblColumnData CD on t.UserID=CD.UserID,t.ColumnID=CD.ColumnID

【讨论】:

  • tblUsers 有 700 万条记录,看起来交叉连接会导致一些性能问题。即使为特定的 UserID 设置了 WHERE,它也会返回 19,088 :s
  • 在这种情况下你必须使用 cross join
  • 是的,我按照您的示例进行了尝试,但没有成功。这是我在真实数据库上的 SQL。 SELECT * FROM (SELECT DISTINCT u.MailUserID,c.MLColumnID, c.MLColumnName FROM ss_tblMailUsers u CROSS JOIN ss_tblMLColumns c WHERE u.MailListID=28231) c LEFT JOIN ss_tblMLColumnData CD ON c.MLColumnID=CD.MLColumnID
猜你喜欢
  • 2014-06-04
  • 2014-03-28
  • 2017-10-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-05
相关资源
最近更新 更多