进阶查询语句.md 9.8 KB


notion-id: 294ca4d7-cb7b-807e-8642-da53557f6b

SQL 查询语句分析与解释

1. 查看 wiz_kb 表的 GUID 格式

-- 查看wiz_kb表的GUID格式(前10条)SELECT
  KB_GUID, KB_NAME
FROM wizasent.wiz_kb
where KB_NAMEISnotnull;

解释: 此查询用于查看 wiz_kb 表中知识库的 GUID 格式和对应的名称。KB_GUID 字段存储的是知识库的唯一标识符,KB_NAME 是知识库的名称。WHERE 条件过滤掉名称为空的记录。


2. 查看 wiz_tag 表的 GUID HEX 格式

SELECT
  HEX(KB_GUID)AS KB_GUID
FROM wizksent.wiz_tag;

解释: 此查询将 wiz_tag 表中的 KB_GUID 字段转换为十六进制格式显示。HEX() 函数用于将二进制数据转换为可读的十六进制字符串,便于后续的匹配和比较操作。


3. 查询能匹配的 wiz_tag 记录

-- 查询能匹配上的wiz_tag记录(显示HEX格式的GUID)
SELECT DISTINCT
    HEX(wt.KB_GUID)as KB_GUID_HEX,
    HEX(wt.TAG_GUID),
    wt.TAG_NAME,
    wk.KB_NAME,
    wk.KB_GUIDas KB_GUID_ORIGINAL
FROM wizksent.wiz_tag wt
INNERJOIN wizasent.wiz_kb wk
ON HEX(wt.KB_GUID) = UPPER(REPLACE(wk.KB_GUID, '-', ''))
WHERE wk.KB_NAMEISNOTNULLORDERBY wt.TAG_NAME, wk.KB_NAME;

解释:

  • 使用 INNER JOIN 连接 wiz_tag 和 wiz_kb 表
  • 连接条件:将 wiz_tag.KB_GUID 转换为 HEX 格式,与去除连字符并大写的 wiz_kb.KB_GUID 进行匹配
  • UPPER(REPLACE(wk.KB_GUID, '-', '')) 用于处理 GUID 格式差异
  • 结果显示匹配成功的标签信息及其对应的知识库信息

4. 查看文档与标签的关联关系

SELECT
    HEX(dt.TAG_GUID), d.*
FROM wizksent.wiz_document d
INNER JOIN wizksent.wiz_document_tag dt
    ON d.DOCUMENT_GUID = dt.DOCUMENT_GUID
ORDER BY d.DT_CREATED;

解释: 此查询显示文档与标签的关联关系,通过 wiz_documentwiz_document_tag 表的连接,获取每个文档对应的标签 GUID(以 HEX 格式显示),并按创建时间排序。


5. 完整的文档-标签-知识库关联查询

SELECT
    HEX(dt.TAG_GUID) AS DOC_TAG_GUID_HEX,
    d.*,
    wt.TAG_NAME,
    wk.KB_NAME
FROM wizksent.wiz_document d
INNER JOIN wizksent.wiz_document_tag dt
    ON d.DOCUMENT_GUID = dt.DOCUMENT_GUID
INNER JOIN wizksent.wiz_tag wt
    ON HEX(dt.TAG_GUID) = HEX(wt.TAG_GUID)
INNER JOIN wizasent.wiz_kb wk
    ON HEX(wt.KB_GUID) = UPPER(REPLACE(wk.KB_GUID, '-', ''))
WHERE wk.KB_NAME IS NOT NULL
ORDER BY d.DT_CREATED;

解释: 这是一个四级联表查询:

  1. wiz_document ↔ wiz_document_tag:通过 DOCUMENT_GUID 关联
  2. wiz_document_tag ↔ wiz_tag:通过 TAG_GUID 关联(HEX 格式匹配)
  3. wiz_tag ↔ wiz_kb:通过 KB_GUID 关联(HEX 格式匹配处理)
  4. 最终显示文档详情、标签名称和知识库名称

6. 按知识库和标签分组统计文档数量

SELECT
    wk.KB_NAME AS 一级目录,
    wt.TAG_NAME AS 二级目录,
    COUNT(*) AS 文档数量
FROM wizksent.wiz_document d
INNER JOIN wizksent.wiz_document_tag dt
    ON d.DOCUMENT_GUID = dt.DOCUMENT_GUID
INNER JOIN wizksent.wiz_tag wt
    ON dt.TAG_GUID = wt.TAG_GUID
INNER JOIN wizasent.wiz_kb wk
    ON HEX(wt.KB_GUID) = UPPER(REPLACE(wk.KB_GUID, '-', ''))
WHERE wk.KB_NAME IS NOT NULL
GROUP BY wk.KB_NAME, wt.TAG_NAME
ORDER BY wk.KB_NAME, wt.TAG_NAME;

解释:

  • 按知识库名称(一级目录)和标签名称(二级目录)进行分组
  • 使用 COUNT(*) 统计每个分组中的文档数量
  • GROUP BY 确保统计的正确性
  • 结果按知识库名称和标签名称排序,便于阅读

7. 按时间范围统计文档数量

SELECT 
    wk.KB_NAME as 一级目录,
    wt.TAG_NAME as 二级目录,
    COUNT(*) as 文档数量,
    MIN(d.DT_CREATED) as 最早创建时间,
    MAX(d.DT_CREATED) as 最晚创建时间
FROM wizksent.wiz_document d
INNER JOIN wizksent.wiz_document_tag dt 
    ON d.DOCUMENT_GUID = dt.DOCUMENT_GUID
INNER JOIN wizksent.wiz_tag wt 
    ON dt.TAG_GUID = wt.TAG_GUID
INNER JOIN wizasent.wiz_kb wk 
    ON HEX(wt.KB_GUID) = UPPER(REPLACE(wk.KB_GUID, '-', ''))
WHERE wk.KB_NAME IS NOT NULL
    AND d.DT_CREATED >= '2025-10-01 00:00:00'
    AND d.DT_CREATED <= '2025-10-30 23:59:59'
GROUP BY wk.KB_NAME, wt.TAG_NAME
ORDER BY wk.KB_NAME, wt.TAG_NAME;

解释:

  • 在分组统计的基础上添加了时间范围筛选
  • 只统计 2025年10月1日至10月30日期间创建的文档
  • 新增 MIN() 和 MAX() 函数显示每个分组中文档的最早和最晚创建时间
  • 适用于按时间段分析文档分布情况

总结

这些 SQL 语句展示了从多个表中提取和分析数据的方法,包括:

  • 表连接技术(INNER JOIN)
  • 数据格式转换(HEX()、UPPER()、REPLACE())
  • 分组统计(GROUP BY、COUNT())
  • 时间范围筛选
  • 多级目录结构的数据分析

这些查询对于文档管理系统中的数据分析和报表生成非常有用。

-- ============================================================
-- 查询目的:获取指定时间范围内的文档信息及其关联的标签、知识库和用户信息
-- ============================================================

SELECT
    -- 将标签 GUID 转换为十六进制格式便于查看
    HEX(dt.TAG_GUID) AS DOC_TAG_GUID_HEX,
    -- 文档表的所有字段
    d.*,
    -- 标签名称
    wt.TAG_NAME,
    -- 知识库名称
    wk.KB_NAME,
    -- 用户别名(显示名称)
    ubr.USER_ALIAS

-- 主表:文档表
FROM wizksent.wiz_document d

-- 连接文档标签关联表(获取文档对应的标签)
INNER JOIN wizksent.wiz_document_tag dt
    ON d.DOCUMENT_GUID = dt.DOCUMENT_GUID

-- 连接标签表(获取标签详细信息)
INNER JOIN wizksent.wiz_tag wt
    ON HEX(dt.TAG_GUID) = HEX(wt.TAG_GUID)

-- 连接知识库表(获取知识库名称)
-- 注意:这里使用 HEX 函数和字符串替换来匹配 GUID 格式差异
INNER JOIN wizasent.wiz_kb wk
    ON HEX(wt.KB_GUID) = UPPER(REPLACE(wk.KB_GUID, '-', ''))

-- 左连接用户表(通过文档所有者的邮箱获取用户 GUID)
-- 使用 LEFT JOIN 是因为可能存在文档所有者邮箱在用户表中不存在的情况
LEFT JOIN wizasent.wiz_user wu
    ON d.DOCUMENT_OWNER = wu.EMAIL

-- 左连接业务用户角色表(获取用户的显示别名)
-- 使用 LEFT JOIN 是因为用户可能没有对应的角色信息
LEFT JOIN wizasent.wiz_biz_user_role ubr
    ON wu.USER_GUID = ubr.USER_GUID

-- 筛选条件
WHERE 
    -- 排除知识库名称为空的记录
    wk.KB_NAME IS NOT NULL
    -- 文档创建时间大于等于 2025年10月1日
    AND d.DT_CREATED >= '2025-10-01 00:00:00'
    -- 文档创建时间小于 2026年1月2日 23:59:59
    AND d.DT_CREATED <  '2026-01-02 23:59:59'

-- 按文档创建时间升序排列
ORDER BY d.DT_CREATED;

-- ============================================================
-- 注意事项:
-- 1. wizksent 和 wizasent 是两个不同的数据库/schema
-- 2. GUID 格式在不同表中可能不一致(有的带连字符,有的不带)
-- 3. 时间范围跨越了 2025-10 到 2026-01 约3个月
-- ============================================================

查询时间范围内文章并且显示用户名和团队别名

SELECT
    d.DOCUMENT_GUID,
    d.DOCUMENT_TITLE,
    d.BODY_TEXT,
    d.DOCUMENT_OWNER,
    d.DT_CREATED        AS created_time,
    wu.USER_GUID,
    wu.DISPLAYNAME,
    ubr.USER_ALIAS
-- 数据来源文章表简称d 
FROM wizksent.wiz_document d
-- 结合用户数据的EMAIL和MOBILE来查询USER_GUID
LEFT JOIN wizasent.wiz_user wu
    ON d.DOCUMENT_OWNER = wu.EMAIL
    OR d.DOCUMENT_OWNER = wu.MOBILE
-- 查询USER_GUID的数据来获取USER_ALIAS
LEFT JOIN wizasent.wiz_biz_user_role ubr
    ON wu.USER_GUID = ubr.USER_GUID
WHERE 
    d.DT_CREATED >= '2025-10-01 00:00:00'
    AND d.DT_CREATED <  '2026-01-02 23:59:59'
ORDER BY d.DT_CREATED;

不可视符号占用

你的 SQL 可以改成:

    SELECT
        d.DOCUMENT_GUID,
        d.DOCUMENT_TITLE,
        d.BODY_TEXT,
        d.DOCUMENT_OWNER,
        d.DT_CREATED AS created_time,
        wu.USER_GUID,
        wu.DISPLAYNAME,
        ubr.USER_ALIAS
    FROM wizksent.wiz_document d
    LEFT JOIN wizasent.wiz_user wu
        ON d.DOCUMENT_OWNER = wu.EMAIL
        OR d.DOCUMENT_OWNER = wu.MOBILE
    LEFT JOIN wizasent.wiz_biz_user_role ubr
        ON wu.USER_GUID = ubr.USER_GUID
    WHERE
        d.DT_CREATED >= '2026-04-01 00:00:00'
        AND d.DT_CREATED <= '2026-04-30 23:59:59'

        AND d.BODY_TEXT IS NOT NULL
        AND TRIM(
            REPLACE(
                REPLACE(
                    REPLACE(d.BODY_TEXT, CHAR(10), ''),
                    CHAR(13), ''
                ),
                CHAR(9), ''
            )
        ) <> ''

    ORDER BY d.DT_CREATED;

    如果还想顺便过滤 HTML 空白占位符,比如 <p><br></p>、&nbsp;,可以用更强一点的版本:

    AND d.BODY_TEXT IS NOT NULL
    AND TRIM(
        REPLACE(
            REPLACE(
                REPLACE(
                    REPLACE(
                        REPLACE(
                            REPLACE(
                                REPLACE(
                                    REPLACE(d.BODY_TEXT,
                                        CHAR(10), ''
                                    ),
                                    CHAR(13), ''
                                ),
                                CHAR(9), ''
                            ),
                            '&nbsp;', ''
                        ),
                        '<p><br></p>', ''
                    ),
                    '<p><br /></p>', ''
                ),
                '<br>', ''
            ),
            '<br/>', ''
        )
    ) <> ''

    结论:

    赵甜这条不是 NULL,也不是空字符串,而是 BODY_TEXT = 换行符。

    所以你之前的 TRIM(d.BODY_TEXT) <> '' 没挡住它。