简体   繁体   English

Where 子句中的 SQL 嵌套大小写

[英]SQL Nested Case in Where Clause

I have a sample table with following structure and data.我有一个具有以下结构和数据的示例表。

在此处输入图片说明

I have to select value from this table with respect to the name, type and subtype.我必须从这个表中选择关于名称、类型和子类型的值。 If any one of the column value is not matching the condition then value with 'all' should be picked.如果列值中的任何一个与条件不匹配,则应选择带有 'all' 的值。 Below is the query created.下面是创建的查询。 declare name varchar default 'name1' declare type varchar default 'type1' declare subtype varchar default 'subtype1'声明名称 varchar 默认 'name1' 声明类型 varchar 默认 'type1' 声明子类型 varchar 默认 'subtype1'

SELECT * FROM sampledata sd 
where
    case when (exists(select 1 from sampledata where name = :name))     
        then sd.name = :name and
        case when exists (select 1 from sampledata where name = :name and type = :type)         
            then sd.type = :type and
                case when exists (select 1 from sampledata where name = :name and type = :type and subtype = :subtype)  
                    then sd.subtype = :subtype 
                    else sd.subtype = 'all' 
                end
            else sd.type = 'all' and    
                case when exists (select 1 from sampledata where name = :name and type = 'all' and subtype = :subtype)  
                    then sd.subtype = :subtype 
                    else sd.subtype = 'all' 
                end
        end             
    else sd.name = 'all' and         
        case when exists (select 1 from sampledata where name = 'all' and type = :type)         
            then sd.type = :type and 
                case when exists (select 1 from sampledata where name = 'all' and type = :type and subtype = :subtype)  
                    then sd.subtype = :subtype 
                    else sd.subtype = 'all'
                end
            else sd.type = 'all' and    
                case when exists (select 1 from sampledata where name = 'all' and type = 'all' and subtype = :subtype)  
                    then sd.subtype = :subtype 
                    else sd.subtype = 'all' 
                end
        end
end

This is the result for 'name1', 'type1' and 'subtype1'.这是“name1”、“type1”和“subtype1”的结果。

在此处输入图片说明

This is the result for 'name3', 'type3' and 'subtype1' parameters.这是“name3”、“type3”和“subtype1”参数的结果。

在此处输入图片说明

CREATE TABLE sampledata (
"name" varchar NULL,
"type" varchar NULL,
subtype varchar NULL,
value float4 NULL
);

INSERT INTO sampledata
("name", "type", subtype, value)
VALUES ('name1', 'type1', 'subtype1', 10),
('name1', 'type2', 'subtype2', 20),
('name1', 'type1', 'all', 30),
('name1', 'type2', 'all', 40),
('name1', 'all', 'subtype1', 50),
('name1', 'all', 'subtype2', 60),
('name1', 'all', 'all', 70),
('all', 'type1', 'subtype1', 80),
('all', 'type2', 'subtype2', 90),
('all', 'all', 'subtype1', 100),
('all', 'all', 'subtype2', 110),
('all', 'all', 'all', 120);

The query is working fine and I would like to know if there an optimized logic without using the nested case to achieve the same result.查询工作正常,我想知道是否有优化的逻辑而不使用嵌套案例来实现相同的结果。

Thanks in advance.提前致谢。

I would suggest the following approach :我建议采用以下方法:

WITH list AS
(   SELECT name, type, subtype
         , case when name = 'all' then 2 else 1 end AS name_weight
         , case when type= 'all' then 2 else 1 end AS type_weight
         , case when subtype= 'all' then 2 else 1 end AS subtype_weight
      FROM sampledata sd
     WHERE (name = 'name3' OR name = 'all')
       AND (type = 'type3' OR type = 'all')
       AND (subtype = 'subtype1' OR subtype = 'all')
)
SELECT name, type, subtype
  FROM list
 ORDER BY (name_weight*type_weight*subtype_weight) ASC
 LIMIT 1

Then this query will return a random result if both rows exist in the table :如果表中存在两行,则此查询将返回随机结果:

(all, type3,subtype1) and (name3,all,subtype1) (all, type3,subtype1) 和 (name3,all,subtype1)

because they will get the same weight = name_weight*type_weight*subtype_weight, so the ORDER BY clause must be refined for this kind of case, for example by defining different weights for name, type, subtype so that to prioritize their importance因为它们会得到相同的权重 = name_weight*type_weight*subtype_weight,所以必须针对这种情况细化 ORDER BY 子句,例如通过为 name、type、subtype 定义不同的权重,以便优先考虑它们的重要性

Enumerate and order:枚举和排序:


\i tmp.sql

        -- The table definition
        -- ---------------------------------
CREATE TABLE sampledata
        ( id serial primary key
        , name text
        , type text
        , subtype text
        , val integer
        );

        -- I had to type in the data myself
        -- ---------------------------------
INSERT INTO sampledata ( name , type , subtype ,val)
VALUES ('name1' , 'type1' , 'subtype1', 10)
        , ('name1' , 'type2' , 'subtype2', 20)
        , ('name1' , 'type1' , 'all', 30)
        , ('name1' , 'type2' , 'all', 40)
        , ('name1' , 'all' , 'subtype1', 50)
        , ('name1' , 'all' , 'subtype2', 60)
        , ('name1' , 'all' , 'all', 70)
        , ('all' , 'type1' , 'subtype1', 80)
        , ('all' , 'type2' , 'subtype2', 90)
        , ('all' , 'all' , 'subtype1', 100)
        , ('all' , 'all' , 'subtype2', 110)
        , ('all' , 'all' , 'all', 120)
        ;

SELECT * FROM sampledata ;

        -- Prepared query to allow parameters
        -- ------------------------------------
PREPARE omg(text,text,text) AS
SELECT *
        , 0::int
        + 40*(name = $1)::int
        + 20*(type = $2)::int
        + 10*(subtype = $3)::int
        + 4*(name = 'all' )::int
        + 2*(type = 'all' )::int
        + 1*(subtype = 'all' )::int
        AS flag
FROM sampledata sd
WHERE name in($1, 'all' )
AND type in($2, 'all' )
AND subtype in($3, 'all' )
ORDER BY flag DESC
LIMIT 1
        ;

        -- Example#1
        -- -----------
EXECUTE omg('name1' , 'type1' , 'subtype1' );
        -- Example#2
        -- -----------
EXECUTE omg('name3' , 'type3' , 'subtype1' );

Results:结果:


DROP SCHEMA
CREATE SCHEMA
SET
CREATE TABLE
INSERT 0 12
 id | name  | type  | subtype  | val 
----+-------+-------+----------+-----
  1 | name1 | type1 | subtype1 |  10
  2 | name1 | type2 | subtype2 |  20
  3 | name1 | type1 | all      |  30
  4 | name1 | type2 | all      |  40
  5 | name1 | all   | subtype1 |  50
  6 | name1 | all   | subtype2 |  60
  7 | name1 | all   | all      |  70
  8 | all   | type1 | subtype1 |  80
  9 | all   | type2 | subtype2 |  90
 10 | all   | all   | subtype1 | 100
 11 | all   | all   | subtype2 | 110
 12 | all   | all   | all      | 120
(12 rows)

PREPARE
 id | name  | type  | subtype  | val | flag 
----+-------+-------+----------+-----+------
  1 | name1 | type1 | subtype1 |  10 |   70
(1 row)

 id | name | type | subtype  | val | flag 
----+------+------+----------+-----+------
 10 | all  | all  | subtype1 | 100 |   16
(1 row)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM