SQL查询以有条件地选择字段值

时间:2018-02-06 12:15:57

标签: sql postgresql

我有一个连接3个表的SQL查询,以返回所需的数据。查询如下:

SELECT (s.user_created, 
        u.first_name, 
        u.last_name, 
        u.email, 
        s.school_name, 
        p.plan_name, 
        substring( a.message, 11), u.phone1) 
FROM cb_school s
inner join ugrp_user u 
    on s.user_created = u.user_id 
inner join cb_plan p 
    on s.current_plan = p.plan_id 
inner join audit a 
    on u.user_id = a.user_id
where s.type = 'sample' 
      and a.module_short = 'sample-user' 
      and s.created_time > current_timestamp - interval '10 day';

如果存在所有属性,则查询可以正常工作。现在,对于我的几行,以下值将缺少a.module_short = 'sample-user'。但由于我将其作为AND条件包含在内,因此不会返回这些行。我试图返回该字段的空字符串,如果它存在,否则根据我当前的查询返回值。有没有办法实现这一目标。

4 个答案:

答案 0 :(得分:1)

认为您可以使用CASE WHEN语句,如下所示:

SELECT CASE WHEN a.module_short = 'sample-user' THEN a.module_short
       ELSE '' END AS a.module_short
FROM TableA

答案 1 :(得分:0)

你可以使用COALESCE它返回第一个not null。

SELECT  COALESCE(a.module_short,'')
FROM TableA  AS a

答案 2 :(得分:0)

您希望显示至少拥有一个module_short的所有用户。 如果module_short包含' sample-user'然后它应该显示它,否则它应该显示NULL作为module_short。每个用户只需要1行,即使它有多个module_shorts。

您可以使用CTEROW_NUMBER()CASE clause来解决此问题。

示例问题

我有3张桌子。

  • 用户:具有ID的用户
  • 模块:ID为
  • 的模块
  • UserModules:用户和模块之间的链接。您的用户可以拥有多个模型。

我需要一个查询,它返回所有至少有1个模块,其中包含2列UserName和ModuleName的用户。 每个用户只有一行1行。如果用户具有该模块,ModuleName应仅显示SQL。否则它应该不显示模块。

示例表:

用户:

id  name    
1   Manuel  
2   John    
3   Doe     

模块:

id  module
1   StackOverflow
2   SQL
3   StackExchange
4   SomethingElse

UserModules:

id  module_id   user_id
1   1           2
2   1           3
4   2           2
5   2           3
6   3           1
7   3           3
8   4           1
9   4           3

示例查询:

with CTE as (
select
    u.name as UserName
    , CASE
        WHEN m.module = 'SQL' THEN 'SQL' ELSE NULL END as ModuleName
    , ROW_NUMBER() OVER(PARTITION BY u.id
                                 ORDER BY (CASE
        WHEN m.module = 'SQL' THEN 'Ja' ELSE NULL END) DESC) as rn
from UserModules as um
    inner join Users as u
        on um.user_id = u.id
    inner join Modules as m
        on um.module_id = m.id
        )
select UserName, ModuleName from CTE
where rn = 1

示例结果:

UserName    ModuleName
Manuel      NULL        
John        SQL         
Doe         SQL         

您的查询如下所示:

with UsersWithRownumbersBasedOnModule_short as (
SELECT s.user_created, 
        u.first_name, 
        u.last_name, 
        u.email, 
        s.school_name, 
        p.plan_name, 
        substring( a.message, 11),
        u.phone1)
        CASE    
            WHEN a.module_short = 'sample-user' 
                THEN a.module_short 
            ELSE NULL 
            END AS ModuleShort
        ROW_NUMBER() OVER(PARTITION BY u.user_id ORDER BY (
            CASE    
                WHEN a.module_short = 'sample-user' 
                    THEN a.module_short 
                ELSE NULL 
            END) DESC) as rn
FROM cb_school s
inner join ugrp_user u 
    on s.user_created = u.user_id 
inner join cb_plan p 
    on s.current_plan = p.plan_id 
inner join audit a 
    on u.user_id = a.user_id
where s.type = 'sample' 
      and s.created_time > current_timestamp - interval '10 day';)
select * from UsersWithRownumbersBasedOnModule_short
where rn = 1

PS:我在SELECT之后删除了一个丢失的括号,而SUBSTRING()缺少1个参数,它需要3个。

答案 3 :(得分:0)

    SELECT (s.user_created, 
        u.first_name, 
        u.last_name, 
        u.email, 
        s.school_name, 
        p.plan_name, 
        substring( a.message, 11), u.phone1) 
    FROM cb_school s
    INNER JOIN ugrp_user u 
    ON s.user_created = u.user_id 
    INNER JOIN cb_plan p 
    ON s.current_plan = p.plan_id
    INNER JOIN audit a 
    ON u.user_id = a.user_id
    AND a.module_short = 'sample-user' 
    WHERE s.type = 'sample' 
    AND s.created_time > current_timestamp - interval '10 day';