代码之家  ›  专栏  ›  技术社区  ›  Andy Lester

如何改进此SQL查询?

  •  1
  • Andy Lester  · 技术社区  · 16 年前

    我正在检查_fmd中是否存在行,我查找的isbn可以是isbn参数,也可以是交叉号表中可能有行或可能没有行的另一个isbn。

    select count(*)
    from in_fmd i
    where (description='GN')
        and ( i.isbn in
        (
            select bwi_isbn from bw_isbn where orig_isbn = ?
            union all
            select cast(? as varchar) as isbn
        )
    ) 
    

    实际上,我不关心行的计数,而只关心至少一行的存在。

    这以前是三个独立的查询,我将其压缩为一个,但我认为还有进一步改进的空间。如果重要的话,是PostgreSQL 8.1。

    5 回复  |  直到 7 年前
        1
  •  4
  •   Cade Roux    16 年前

    为什么要麻烦 UNION ALL

    select count(*)
    from in_fmd i
    where (description='GN')
        and (
            i.isbn in (
                select bwi_isbn from bw_isbn where orig_isbn = ?
            )
            or i.isbn = cast(? as varchar)
        )
    

    我可能会用 LEFT JOIN -样式查询而不是 IN 但这更符合个人喜好:

    select count(*)
    from in_fmd i
    left join bw_isbn
        on bw_isbn.bwi_isbn = i.isbn
        and bw_isbn.orig_isbn = ?
    where (i.description='GN')
        and (
            bw_isbn.bwi_isbn is not null
            or i.isbn = cast(? as varchar)
        )
    

    在im上讨论的反演:

    SELECT SUM(ct)
    FROM (
        select count(*) as ct
        from in_fmd i
        inner join bw_isbn
            on bw_isbn.bwi_isbn = i.isbn
            and bw_isbn.orig_isbn = ?
            and i.isbn <> cast(? as varchar)
            and i.description = 'GN'
    
        UNION
    
        select count(*) as ct
        from in_fmd i
        where i.isbn = cast(? as varchar)
            and i.description = 'GN'
    ) AS x
    
        2
  •  1
  •   Jouni K. Seppänen    16 年前

    实际上,我不关心行的计数,而只关心至少一行的存在。

    那查询呢 SELECT ... LIMIT 1 检查调用程序是否得到一个结果行?

        3
  •  1
  •   Learning    16 年前

    除了其他海报上写的,只是改变

    选择计数(*)

    存在(…)

    improve things 相当多

        4
  •  1
  •   C B dkretz    7 年前
    SELECT SUM(ct)
    FROM (select count(*) as ct
          from in_fmd i
          inner join bw_isbn
             on bw_isbn.bwi_isbn = i.isbn
            and bw_isbn.orig_isbn = ?
            and i.isbn <> cast(? as varchar)
            and i.description = 'GN'
          UNION
          select count(*) as ct
          from in_fmd i
          where i.isbn = cast(? as varchar)
            and i.description = 'GN'
         ) AS x
    
        5
  •  0
  •   C B dkretz    7 年前
    select count(*)
    from in_fmd i
    where description = 'GN'
      and exists (select 1 
                  from bwi_isbn 
                  where bw_isbn.bwi_isbn = in_fmd.isbn)