【问题标题】:LEFT JOIN on static list of items?LEFT JOIN 在静态项目列表上?
【发布时间】:2016-10-21 23:29:21
【问题描述】:

DBMS 是 !

动机:我需要对一个表进行左连接,以便每次都能获得相同的消息类型列表,即使结果为零或空。不幸的是,这是一张大表,因此包含SELECT DISTINCT() 的速度非常慢。这些不应该改变,所以我想我会得到一次列表,然后静态地加入它们。

基于另一个 SO 问题,这是我必须替换的 SELECT DISTINCT()

    SELECT 'HS.MESSAGE.GATEWAYREGISTRATIONREQUEST' as MessageBodyClassName
    UNION SELECT 'HS.MESSAGE.MERGEPATIENTREQUEST'
    UNION SELECT 'HS.MESSAGE.PATIENTSEARCHREQUEST'

这会返回与预期完全相同的结果,与 Distinct 查询相同。但是,当我将其插入到我的 JOIN 语句中时,所有计数都归零。

查询失败

SELECT mh.MessageBodyClassName, count(l.MessageBodyClassName) as MessageCount FROM 
    (
        SELECT 'HS.MESSAGE.GATEWAYREGISTRATIONREQUEST' as MessageBodyClassName
        UNION SELECT 'HS.MESSAGE.MERGEPATIENTREQUEST'
        UNION SELECT 'HS.MESSAGE.PATIENTSEARCHREQUEST'
    ) mh LEFT JOIN
    (
        SELECT messageBodyClassName FROM ens.messageheader WHERE TimeCreated > DATEADD(hh, -1, GETUTCDATE())
    ) l ON mh.MessageBodyClassName = l.MessageBodyClassName
GROUP BY mh.MessageBodyClassName

失败的结果

MessageBodyClassName                  MessageCount 
------------------------------------- ------------ 
HS.MESSAGE.GATEWAYREGISTRATIONREQUEST 0            
HS.MESSAGE.MERGEPATIENTREQUEST        0            
HS.MESSAGE.PATIENTSEARCHREQUEST       0

工作查询

SELECT mh.MessageBodyClassName, count(l.MessageBodyClassName) as MessageCount FROM 
    (
        SELECT DISTINCT(MessageBodyClassName) FROM ens.messageheader
    ) mh LEFT JOIN
    (
        SELECT messageBodyClassName FROM ens.messageheader WHERE TimeCreated > DATEADD(hh, -1, GETUTCDATE())
    ) l ON mh.MessageBodyClassName = l.MessageBodyClassName
GROUP BY mh.MessageBodyClassName

工作和预期结果

MessageBodyClassName                  MessageCount 
------------------------------------- ------------ 
HS.MESSAGE.GATEWAYREGISTRATIONREQUEST 0            
HS.MESSAGE.MERGEPATIENTREQUEST        0            
HS.MESSAGE.PATIENTSEARCHREQUEST       54

对于 VKP:为什么结果不同?如何使用文字调整第一个查询以获得正确(相同)的结果?

【问题讨论】:

  • 我不知道你的 dbms。无论如何,我要检查的第一件事是您的列的数据类型。如果它是 char(而不是 varcahr),您可能会在这里找到问题的解决方案
  • mh 中的messageBodyClassName 上的类型是varchar 还是char?好奇它是否是枚举类型,并且您正在比较两种不同的类型。您的工作查询将保留这一点。
  • 根据 DBVis 和 ISC ODBC 驱动程序,它是一个VARCHAR
  • ens.messageheader.messageBodyClassName 中可能有一个空白或特殊(非显示)字符,而不是您的硬编码值。为了证明这一点,请尝试SELECT count(*) from ens.messageheader where messageBodyClassName in ('HS.MESSAGE.GATEWAYREGISTRATIONREQUEST', 'HS.MESSAGE.MERGEPATIENTREQUEST', 'HS.MESSAGE.PATIENTSEARCHREQUEST'),如果您的计数为零,则表中的值与您的硬编码值不匹配。你需要弄清楚为什么。试试len来统计字符或者用ASCII转换成asci字符码,看看有什么意外
  • @scott 如果两者相同。那没有意义。另一件事是您可能在不同的时间运行查询,这就是您得到不同结果的原因?

标签: intersystems-cache sql join left-join intersystems-cache


【解决方案1】:

我能想到的最后一件事是将DISTINCT 查询运行一次到数据库中的永久表中。这样,查询中的内部 SELECT 只需处理这三行。内部查询会丢失DISTINCT,比如

SELECT MessageBodyClassName FROM ens.messageheader_permvals

编辑:以下答案无效

这可能有点远,但如果它不起作用,它可能会帮助您诊断问题。而不是UNION 试试

SELECT MessageBodyClassName FROM ens.messageheader
    WHERE MessageBodyClassName in (
    'HS.MESSAGE.GATEWAYREGISTRATIONREQUEST',        
    'HS.MESSAGE.MERGEPATIENTREQUEST',          
    'HS.MESSAGE.PATIENTSEARCHREQUEST')

只有当这些值实际存在于表中并且与MessageBodyClassName 的格式兼容时才应该返回记录,我们知道使用DISTINCT 版本可以工作。我不知道这样的性能是否会更好,但希望它能对这个问题有所启发。

编辑:以下答案不适用,因为 OP 实际上是在尝试选择文字引用值

您的 UNION 查询中没有 FROM 语句。试试

SELECT 'HS.MESSAGE.GATEWAYREGISTRATIONREQUEST' as MessageBodyClassName
            FROM ens.messageheader
        UNION SELECT 'HS.MESSAGE.MERGEPATIENTREQUEST'
            FROM ens.messageheader
        UNION SELECT 'HS.MESSAGE.PATIENTSEARCHREQUEST'
            FROM ens.messageheader

查询的其余部分看起来正确。

【讨论】:

  • 你错过了这个问题。你不需要FROM
  • 没有FROM,执行需要27秒。添加FROM 语句后,它花费了 90 并返回了相同的结果。 :(
  • 如果有帮助,我真的很支持这个答案! :)
  • @Scott 那么您是否要选择引号中的字符串而不是具有这些名称的列?我认为引号是系统间缓存与我熟悉的更一般的 SQL 的区别
  • 不,我实际上希望那些是名为 MessageBodyClassName 的列的
【解决方案2】:

我同意 xQbert,问题是硬编码值

试试

  SELECT T1.MessageBodyClassName, T2.MessageBodyClassName
  FROM (
          SELECT 'HS.MESSAGE.GATEWAYREGISTRATIONREQUEST' as MessageBodyClassName
    UNION SELECT 'HS.MESSAGE.MERGEPATIENTREQUEST'
    UNION SELECT 'HS.MESSAGE.PATIENTSEARCHREQUEST'
       ) as T1
 LEFT JOIN (
         SELECT DISTINCT(MessageBodyClassName) as MessageBodyClassName
         FROM ens.messageheader
       ) as T2
  ON T1.MessageBodyClassName = T2.MessageBodyClassName

可能的解决方案:创建一个临时表

 CREATE TABLE className as 
         SELECT DISTINCT(MessageBodyClassName) as MessageBodyClassName
         FROM ens.messageheader

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-11-22
    • 2018-10-03
    • 1970-01-01
    • 2018-07-17
    • 2012-10-10
    • 1970-01-01
    • 2016-10-04
    相关资源
    最近更新 更多