【问题标题】:Why does my Query take so long to produce result为什么我的查询需要这么长时间才能产生结果
【发布时间】:2016-09-27 14:54:25
【问题描述】:

我有以下查询需要大约 20-30 秒才能产生结果。我想缩短结果时间,我在前端使用访问来创建查询,并在后端使用 SQL Server。不确定是否有更简单的方法和更快的方法来运行此查询。

这是我的查询:

SELECT DISTINCT 
    [UB-04s].client_id, 
    DATEDIFF("yyyy", [UB-04s]![patient_dob], [UB-04s]![admit_date]) AS [AGE at Admission], 
    invalid_diag_codes_by_age.start_age_yrs, 
    invalid_diag_codes_by_age.end_age_yrs, 
    invalid_diag_codes_by_age.diag_code 
INTO 
    tmp10407
FROM 
    [UB-04s], invalid_diag_codes_by_age
WHERE 
    ((([UB-04s].client_id)=[Forms]![frmUB04s]![client_id]) 
    AND (([UB-04s].dx_Q)=[invalid_diag_codes_by_age].[diag_code])) OR ((([UB-04s].client_id)=[Forms]![frmUB04s]![client_id]) 
    AND (([UB-04s].dx_P)=[invalid_diag_codes_by_age].[diag_code])) OR ((([UB-04s].client_id)=[Forms]![frmUB04s]![client_id]) 
   AND (([UB-04s].dx_O)=[invalid_diag_codes_by_age].[diag_code])) OR ((([UB-04s].client_id)=[Forms]![frmUB04s]![client_id]) 
   AND (([UB-04s].dx_N)=[invalid_diag_codes_by_age].[diag_code])) OR ((([UB-04s].client_id)=[Forms]![frmUB04s]![client_id]) 
   AND (([UB-04s].dx_M)=[invalid_diag_codes_by_age].[diag_code])) OR ((([UB-04s].client_id)=[Forms]![frmUB04s]![client_id]) 
   AND (([UB-04s].dx_L)=[invalid_diag_codes_by_age].[diag_code])) OR ((([UB-04s].client_id)=[Forms]![frmUB04s]![client_id]) 
   AND (([UB-04s].dx_K)=[invalid_diag_codes_by_age].[diag_code])) OR ((([UB-04s].client_id)=[Forms]![frmUB04s]![client_id]) 
   AND (([UB-04s].dx_J)=[invalid_diag_codes_by_age].[diag_code])) OR ((([UB-04s].client_id)=[Forms]![frmUB04s]![client_id]) 
   AND (([UB-04s].dx_I)=[invalid_diag_codes_by_age].[diag_code])) OR ((([UB-04s].client_id)=[Forms]![frmUB04s]![client_id]) 
   AND (([UB-04s].dx_H)=[invalid_diag_codes_by_age].[diag_code])) OR ((([UB-04s].client_id)=[Forms]![frmUB04s]![client_id]) 
   AND (([UB-04s].dx_G)=[invalid_diag_codes_by_age].[diag_code])) OR ((([UB-04s].client_id)=[Forms]![frmUB04s]![client_id]) 
   AND (([UB-04s].dx_F)=[invalid_diag_codes_by_age].[diag_code])) OR ((([UB-04s].client_id)=[Forms]![frmUB04s]![client_id]) 
   AND (([UB-04s].dx_E)=[invalid_diag_codes_by_age].[diag_code])) OR ((([UB-04s].client_id)=[Forms]![frmUB04s]![client_id]) 
   AND (([UB-04s].dx_D)=[invalid_diag_codes_by_age].[diag_code])) OR ((([UB-04s].client_id)=[Forms]![frmUB04s]![client_id]) 
   AND (([UB-04s].dx_C)=[invalid_diag_codes_by_age].[diag_code])) OR ((([UB-04s].client_id)=[Forms]![frmUB04s]![client_id]) 
   AND (([UB-04s].dx_B)=[invalid_diag_codes_by_age].[diag_code])) OR ((([UB-04s].client_id)=[Forms]![frmUB04s]![client_id]) 
   AND (([UB-04s].dx_A)=[invalid_diag_codes_by_age].[diag_code])) OR ((([UB-04s].client_id)=[Forms]![frmUB04s]![client_id]) 
   AND (([UB-04s].principal_dx)=[invalid_diag_codes_by_age].[diag_code]));

这些只是表格中的片段,因为这些表格很大......

表 UB04s 中的字段:

client_id   principal_dx    dx_A    dx_B    dx_C    dx_D    dx_E    dx_F    dx_G    dx_H    dx_I    dx_J    dx_K    dx_L    dx_M    dx_N    dx_O    dx_P    dx_Q
527                                                                     
530     42843   4280    4148    41519   42741   4271    5849    5770    5739        99702   431 2760    44422   28981   28984   2384    78551   42611
531     5715    44489   34839   0785    99682   4589    5723    2762    42518       99779   99811   5180    2689    2769    57142   5680    4471    2894
533     5559    V145                                                                
116     2761    7802    4019    2724    V1582   2768                                                
117     55321       

来自无效诊断代码表的字段:

diag_code   start_age_yrs   end_age_yrs age_range_desc  
04041           0               0.5         0-6 months of age       
27701           0                1          
3070           18                99         
99779           0                1          
5559           15                99         

基本上我正在做的是搜索客户的所有诊断代码,以查看它是否是基于客户年龄的无效诊断代码。

【问题讨论】:

  • 你在那里有一个交叉连接,因为你使用了一个逗号分隔的表列表并且没有在 where 子句中包含连接谓词。这是编写查询的不好方法。 sqlblog.com/blogs/aaron_bertrand/archive/2009/10/08/… 另外,您似乎在这里遇到了一些严重的规范化问题。你似乎有重复的群体违反 1NF 并导致无数的痛苦。最后但并非最不重要的一点是,DATEDIFF 函数不是有效的 sql server 语法。
  • 在不知道表格是什么样子以及您要完成什么的情况下,很难尝试为您重写它。但我不得不说,它确实看起来写得很糟糕。我想您可以使用内部联接代替交叉联接,并使用“WHERE x IN ()”子句代替大量意外事件。
  • 我不能使用连接,因为这会产生不需要的结果。客户端有多个诊断代码,必须存储在单独的字段中,然后将这些代码与另一列中列出所有诊断代码的表进行比较。如果我插入一个连接的问题,它会给我与客户端无关的不必要的诊断代码。
  • 你在这里使用了一个连接....这是一个交叉连接。这很可能是您得到不需要的结果的原因。你的 where 谓词是一团糟。看起来它们是由 Access 中的自动化工具编写的。你需要清理它,这样你才能阅读它。您似乎在其中遇到了许多逻辑挑战。
  • re: “我在前端使用访问来创建查询,并在后端使用 SQL Server。” - 澄清一下,您使用的是普通 在访问中针对驻留在 SQL Server 上的 ODBC 链接表选择查询(与 传递查询 相对)。对吗?

标签: sql sql-server ms-access ms-access-2013


【解决方案1】:

没有真正的细节可以使用,我完全猜测你想要什么。但是使用别名并删除所有额外的括号将有很大帮助。我还使用了 IN 而不是重复的谓词。这不会完全像这样工作,但非常接近。

SELECT DISTINCT u.client_id
    , DateDiff(year, [UB-04s]![patient_dob], [UB-04s]![admit_date]) AS [AGE at Admission]
    , i.start_age_yrs
    , i.end_age_yrs
    , i.diag_code 
INTO tmp10407
FROM [UB-04s] u
cross join invalid_diag_codes_by_age i
WHERE u.client_id = [Forms]![frmUB04s]![client_id] 
AND 
(
    u.dx_Q = i.diag_code
) 
OR 
(
    u.principal_dx = i.diag_code
    AND
    i.diag_code in 
    (
        u.dx_P
        , u.dx_O
        , u.dx_N
        , u.dx_M
        , u.dx_L
        , u.dx_K
        , u.dx_J
        , u.dx_I
        , u.dx_H
        , u.dx_G
        , u.dx_F
        , u.dx_E
        , u.dx_D
        , u.dx_C
        , u.dx_B
        , u.dx_A
    )
)

【讨论】:

  • 感谢@Sean Lange,您的回答让我得到了我需要的一些调整。这是我在 3-5 秒内返回的最终查询。
【解决方案2】:
SELECT DISTINCT u.client_id, DateDiff("yyyy",u.patient_dob,u.admit_date) AS [AGE at Admission], i.start_age_yrs, i.end_age_yrs, i.diag_code INTO tmp10407
FROM [UB-04s] AS u, invalid_diag_codes_by_age AS i
WHERE (((u.client_id)=[Forms]![frmUB04s]![client_id]) 
AND ((i.diag_code) In ([u].[dx_P],[u].[dx_O],[u].[dx_N],[u].[dx_M],[u].[dx_L],[u].[dx_K],[u].[dx_J],[u].[dx_I],[u].[dx_H],[u].[dx_G],[u].[dx_F],[u].[dx_E],[u].[dx_D],[u].[dx_C],[u].[dx_B],[u].[dx_A]))) 
OR (((u.client_id)=[Forms]![frmUB04s]![client_id]) 
AND ((u.principal_dx) In ([i].[diag_code])));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-04-12
    • 2021-07-17
    • 1970-01-01
    • 2011-08-27
    • 2019-11-13
    • 1970-01-01
    相关资源
    最近更新 更多