【问题标题】:Two JOINS from same Table来自同一个表的两个 JOINS
【发布时间】:2019-05-24 23:50:02
【问题描述】:

我有两个表 DocumentXref

Xref 是一种将文档链接到另一个文档的方法。

Xref Table 存储 document 的 id(来自文档表),并且它是链接的 xref(也来自文档表)

我想检索链接到特定文档外部参照文件名列表。

有关我的表格的基本表示,请参阅附图。

以下 SQL 语句检索我想要的 (xref) 文件名,但我希望能够使用文件名而不是 id 来检索它。

任何帮助将不胜感激。谢谢。

【问题讨论】:

  • 你的问题中没有SQL

标签: sql sql-server tsql join select


【解决方案1】:

您需要加入两个表。应该这样做:

SELECT d.filename
FROM 
    Document d
    INNER JOIN Xref x ON x.xref_id = d.id
WHERE x.document_id = ?

您想将问号替换为您要查找其文件名的文档的 ID。

如果您想按文档名称而不是文档 ID 进行搜索,那么您还需要一个 JOIN :

SELECT d.filename
FROM 
    Document d
    INNER JOIN Xref x ON x.xref_id = d.id
    INNER JOIN Document d2 ON d2.id = x.document_id
WHERE d2.filename = ?

注意:这假定每个文档在表外部参照中都有一个链接文档。如果你不想过滤掉没有外部参照的文档,你想使用«LEFT JOIN»而不是«INNER JOIN»。

【讨论】:

  • 感谢您的回复,这想按照我的示例使用“id”,但我不知道“id”我知道文件名。
  • 再次感谢您的回复和时间。不幸的是,这并没有检索到结果,类似于我的尝试......
  • 抱歉,我混淆了我的文件名。这正是我想要的。非常感谢您的时间和回复。真的很感激。
  • 注意:如果文档在xref 中没有链接文档,则INNER JOIN 将排除主文档。
  • @Shawn:没错。我更新了我的答案以具体说明这一点。
【解决方案2】:

如果您想保留没有子文档的文档,请使用LEFT OUTER JOIN 获取所有主文档。

另外,我使用子选择将子文档链接到xref 表,然后将其链接回主文档查询。

SELECT d1.id AS main_docid, d1.filename AS main_filename
    , s1.sub_docid AS sub_docid, s1.sub_filename AS sub_filename
FROM document d1 
LEFT OUTER JOIN (
    SELECT x.document_id AS main_docid 
        , d2.id AS sub_docid
        , d2.filename AS sub_filename
    FROM xref x 
    INNER JOIN document d2 ON x.xref_id = d2.id
) s1 ON d1.id = s1.main_docid
WHERE d1.filename = ??????? /* Whatever filename you are searching for. */

如果您想通过sub_filename 进行搜索,请将您的WHERE 语句更改为WHERE s1.sub_filename = ???????

【讨论】:

    【解决方案3】:

    针对外部参照加入两次,一次获取参考文件文件名,一次搜索主文档的文件名

    SELECT d2.filename
    FROM Document d
    JOIN Xref x ON d.id = x.document_id
    JOIN Document d2 ON d2.id = x.xref_id
    WHERE d.name = ?
    

    例如

    SELECT d2.filename
    FROM Document d
    JOIN Xref x ON d.id = x.document_id
    JOIN Document d2 ON d2.id = x.xref_id
    WHERE d.name = 'D001'
    

    返回

    文件名
    X001

    【讨论】:

    • 感谢您的回复,不幸的是,这没有检索到任何内容...
    • @squatman 更换 ?同时使用“D001”和“D002”,我两次都得到 X001。
    • 啊,是的,我很抱歉。我将 id 列与检索到的查询行 id 混合在一起。非常感谢您的帮助和时间。真的很感激。
    • 实际上,这仍然没有检索到任何内容,这是其他答案之一。
    • @squatman,我现在看到我打错字了,id 而不是 document_id。固定
    【解决方案4】:

    您需要选择您的主要数据,然后在某些字段或列上使用 JOIN。

    LEFT JOIN 将保留左组中的数据。

    INNER JOIN 只会产生匹配项。

    需要确定文件名是否唯一?总之,

    如果您想使用 LEFT JOIN 来保持左侧为空值,请使用:

    SELECT DOCUMENT.filename FROM Xref XREF
    LEFT JOIN Document DOCUMENT ON XREF.document_id = DOCUMENT.id
    -- Filter by filename:
    --WHERE DOCUMENT.filename = ? OR XREF
    

    否则,我建议选择 INNER JOIN 以获得匹配的行:

    SELECT DOCUMENT.filename FROM Xref XREF
    INNER JOIN Document DOCUMENT ON XREF.document_id = DOCUMENT.id
    -- Filter by filename:
    --WHERE DOCUMENT.filename = ?
    

    结果:
    |文件名 |
    | D001 |
    | D002 |

    SELECT * FROM - 将显示每一列,您需要定义将在新视图上显示哪些列。

    编辑 关于您的评论,假设您有两个输入选项,您可以使用:

    SELECT DOCUMENT.filename FROM Xref XREF
    INNER JOIN Document DOCUMENT ON XREF.document_id = DOCUMENT.id
    -- Filter by filename:
    WHERE DOCUMENT.filename = ? XREF.id = ?
    

    【讨论】:

    • 感谢您的回复,不幸的是,这没有检索到任何内容...
    • 您能描述一下预期的结果吗?另外,请注意 WHERE 条件和使用方式。
    • 假设我正在查看外部参照表中的“D001”,我们可以看到它链接到“X001”。因此,查看文件名“D001”我希望检索“X001”。再次感谢。
    • 我不确定 X001 是什么,因为您没有此 ID,但我猜它是 XREF.id。将两个表连接在一起后,您可以使用 WHERE 进行过滤,您可以使用 OR 来查看不同的列。请参阅我的编辑。
    【解决方案5】:

    其他解决方案适用于单级搜索。如果您想要多级搜索,您可以使用 CTE,假设数据中没有循环:

    with
    x as (
      select id, filename from document where filename = 'mydoc1.txt'
      union all
      select d.id, d.filename
      from x
      join xref r on r.document_id = x.id
      join document d on d.id = r.xref_id
    )
    select * from x;
    

    【讨论】:

    • 感谢您的回复,不幸的是,这只是检索我指定的文件名。
    猜你喜欢
    • 2013-06-10
    • 1970-01-01
    • 2021-09-07
    • 2011-03-25
    • 2019-11-20
    • 2022-11-14
    • 2013-11-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多