我已经研究了很长时间并已经广泛研究过这个问题;到目前为止,没有任何相似之处。 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_date
和col_hour
s,其中至少有col_name
个col_volume
用于该特定col_date
}和col_hour
不符合要求。 (例如,我仍然会收到包含col_date = 2010-12-31
和col_hour = 5
的记录条目,但col_name = "a"
的{{1}}只有col_volume = 200
的{{1}}。日期和小时不应出现在查询中,因为“a”的音量不是> = 600,即使“b”符合其音量要求,即> = 550.)
如果所有这些都令人困惑,这里有样本表,样本正确的查询结果,所以你可以忘记上面的所有内容并继续前进:
表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
答案 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推断您正在寻找以下行:
因此,要将其转换为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