类似SQL函数的WHERE语句

时间:2015-04-28 06:34:10

标签: sql sqlite

我已经研究了很长时间并已经广泛研究过这个问题;到目前为止,没有任何相似之处。 tl; dr under

以下是我的问题。

我正在尝试在SQLite中使用条件过滤创建一个SELECT语句,它有点像函数。下面的示例伪代码:

SELECT col_date, col_hour FROM table1 JOIN table2 
ON table1.col_date = table2_col_date AND table1.col_hour = table2.col_hour AND table1.col_name = table2.col_name
    WHERE
        IF table2.col_name = "a" THEN {filter these records further such that its table2.col_volume >= 600} AND
        IF table2.col_name = "b" THEN {filter these records further such that its table2.col_volume >= 550}
        BUT {if any of these two statements are not met completely, do not get any of the col_date, col_hour}

*我知道SQLite不支持IF语句,但这只是为了表明我的意图。

这是我到目前为止所做的事情。根据{{​​3}}文章,可以将CASE子句转换为布尔逻辑,这样您将在此处看到:

SELECT table1.col_date, table1.col_hour FROM table1 INNER JOIN table2 
ON table1.col_date = table2.col_date AND table1.col_hour = table2.col_hour AND table1.col_name = table2.col_name
    WHERE
        ((NOT table2.col_name = "a") OR table2.col_volume >= 600) AND
        ((NOT table2.col_name = "b") OR table2.col_volume >= 550)

在这种语法中,问题是我仍然得到col_datecol_hour s,其中至少有col_namecol_volume用于该特定col_date }和col_hour不符合要求。 (例如,我仍然会收到包含col_date = 2010-12-31col_hour = 5的记录条目,但col_name = "a"的{​​{1}}只有col_volume = 200的{​​{1}}。日期和小时不应出现在查询中,因为“a”的音量不是> = 600,即使“b”符合其音量要求,即> = 550.)

对于tl; dr

如果所有这些都令人困惑,这里有样本表,样本正确的查询结果,所以你可以忘记上面的所有内容并继续前进:

表1

col_name = "b"

表2

col_volume = 900

正确的查询结果(使用col_date,col_hour,col_name,extra1,extra2 2010-12-31,4,"a","hi",1 2010-12-31,4,"a","he",1 2010-12-31,4,"a","ho",1 2010-12-31,5,"a","hi",1 2010-12-31,5,"a","he",1 2010-12-31,5,"a","ho",1 2010-12-31,6,"a","hi",1 2010-12-31,6,"a","he",1 2010-12-31,6,"a","ho",1 2010-12-31,4,"b","hi",1 2010-12-31,4,"b","he",1 2010-12-31,4,"b","ho",1 2010-12-31,5,"b","hi",1 2010-12-31,5,"b","he",1 2010-12-31,5,"b","ho",1 2010-12-31,6,"b","hi",1 2010-12-31,6,"b","he",1 2010-12-31,6,"b","ho",1 过滤器:600表示“a”,550表示“b”)应为:

col_date,col_hour,col_name,col_volume
2010-12-31,4,"a",750
2010-12-31,4,"b",750
2010-12-31,5,"a",200
2010-12-31,5,"b",900
2010-12-31,6,"a",700
2010-12-31,6,"b",800

4 个答案:

答案 0 :(得分:2)

试试这个:

      SELECT table1.col_date, 
             table1.col_hour 
        FROM table1 
  INNER JOIN table2
          ON table1.col_date = table2.col_date 
         AND table1.col_hour = table2.col_hour 
         AND table1.col_name = table2.col_name
       WHERE EXISTS ( -- here I'm appling the filter logic 
                      select col_date,
                             col_hour
                        from table2 sub
                       where (col_name = 'a' and col_volume >= 600) 
                          or (col_name = 'b' and col_volume >= 550) 
                         and sub.col_date = table2.col_date 
                         and sub.col_hour = table2.col_hour 
                         and sub.col_name = table2.col_name
                    group by col_date,
                             col_hour
                      having count(1) = 2 -- I assume there could be only two rows:
                                          -- one for 'a' and one for 'b'
                    ) 

您可以在SQLfiddle

中查看此演示

最后,您显示了用于连接的Table1中的相同列,但我想这只是为了这个示例

答案 1 :(得分:1)

对于exists子句中的不同条件,您可以尝试使用case和相关子查询与where

select t1.col_date
     , t1.col_hour
from table1 t1 
where exists ( select t2.col_volume
               from table2 t2
               where t2.col_date = t1.col_date
                 and t2.col_hour = t1.col_hour
                 and t2.col_name in ('a', 'b')
               group by t2.col_volume
               having count(t2.col_name >= case when t2.col_name = 'a' then 600 else 550 end) = (select count(*) from table2 where col_name = t2.col_name))

答案 2 :(得分:0)

您的布尔转换是错误的。 您的IF推断您正在寻找以下行:

  • table2.col_name =" a"和col_volume> = 600
  • table2.col_name =" b"和col_volume> = 550
  • (隐含地)col_name
  • 的其他值

因此,要将其转换为SQL:

SELECT     table1.col_date, table1.col_hour 
FROM       table1 
INNER JOIN table2 ON table1.col_date = table2.col_date AND
           table1.col_hour = table2.col_hour
WHERE      (table2.col_name = 'a' AND table2.col_volume >= 600) OR
           (table2.col_name = 'b' AND table2.col_volume >= 550) OR
           (table2.col_name NOT IN ('a', 'b'))

答案 3 :(得分:0)

我想我有一个答案(对 @mucio 的“HAVING”条款有很大的帮助;看起来我必须加以说明。)

显然,该方法是一个简单的子查询,其中外部查询将进行连接。这是一个解决方法(不是我发布的问题的直接答案,我不得不用这种方法重新组织我的程序流程),但它完成了工作。

以下是示例代码:

SELECT table1.col_date, table1.col_hour 
FROM table1 
INNER JOIN 
    (
        SELECT col_date, col_hour 
        FROM table2 
        WHERE 
        (col_name = 'a' AND col_volume >= 600) OR 
        (col_name = 'b' AND col_volume >= 550) 
        GROUP BY col_date, col_hour 
        HAVING COUNT(1) = 2
    ) tb2 
ON 
table1.col_date = tb2.col_date AND 
table1.col_hour = tb2.col_hour 
GROUP BY table1.col_date, table1.col_hour