簡體   English   中英

結果在where子句中的PostgreSQL用例

[英]PostgreSQL use case when result in where clause

我使用復雜的CASE WHEN來選擇值。 我想在WHERE子句中使用此結果,但Postgres說列'd'不存在。

SELECT id, name, case when complex_with_subqueries_and_multiple_when END AS d
FROM table t WHERE d IS NOT NULL
LIMIT 100, OFFSET 100;

然后我想我可以像這樣使用它:

select * from (
    SELECT id, name, case when complex_with_subqueries_and_multiple_when END AS d
    FROM table t 
    LIMIT 100, OFFSET 100) t
WHERE d IS NOT NULL;

但是現在我沒有獲得100行的結果。 可能(我不確定)我可以在select case語句之外使用LIMIT和OFFSET(其中WHERE語句是),但我認為(我不確定為什么)這將是性能損失。

Case返回數組或null。 如果case語句的結果為null,那么排除某些行的最佳/最快方法是什么? 我需要100行(如果不存在則更少 - 當然)。 我正在使用Postgres 9.4。

編輯:

SELECT count(*) OVER() AS count, t.id, t.size, t.price, t.location, t.user_id, p.city, t.price_type, ht.value as houses_type_value, ST_X(t.coordinates) as x, ST_Y(t.coordinates) AS y, 
CASE WHEN t.classification='public' THEN 
ARRAY[(SELECT i.filename FROM table_images i WHERE i.table_id=t.id ORDER BY i.weight ASC LIMIT 1), t.description] 
WHEN t.classification='protected' THEN 
ARRAY[(SELECT i.filename FROM table_images i WHERE i.table_id=t.id ORDER BY i.weight ASC LIMIT 1), t.description]
WHEN t.id IN (SELECT rl.table_id FROM table_private_list rl WHERE rl.owner_id=t.user_id AND rl.user_id=41026) THEN 
ARRAY[(SELECT i.filename FROM table_images i WHERE i.table_id=t.id ORDER BY i.weight ASC LIMIT 1), t.description]
ELSE null
END AS main_image_description
FROM table t LEFT JOIN table_modes m ON m.id = t.mode_id 
LEFT JOIN table_types y ON y.id = t.type_id 
LEFT JOIN post_codes p ON p.id = t.post_code_id 
LEFT JOIN table_houses_types ht on ht.id = t.houses_type_id 
WHERE datetime_sold IS NULL AND datetime_deleted IS NULL AND t.published=true AND coordinates IS NOT NULL AND coordinates && ST_MakeEnvelope(17.831490030182, 44.404640972306, 12.151558389557, 47.837396630872) AND main_image_description IS NOT NULL
GROUP BY t.id, m.value, y.value, p.city, ht.value ORDER BY t.id LIMIT 100 OFFSET 0

要在WHERE子句中使用CASE WHEN結果,您需要將其包裝在子查詢中,就像您一樣或在視圖中。

SELECT * FROM (
    SELECT id, name, CASE 
        WHEN name = 'foo' THEN true
        WHEN name = 'bar' THEN false
        ELSE NULL
        END AS c
    FROM case_in_where
) t WHERE c IS NOT NULL

使用包含1,'foo',2,'bar',3,'baz'的表格,這將返回記錄1和2.我不知道這個SQL小提琴將持續多久,但這是一個例子: http: //sqlfiddle.com/#!15/1d3b4/3 另請參閱https://stackoverflow.com/a/7950920/101151

如果從偏移量100開始的那100行包含d計算為NULL的記錄,則您的限制返回少於100行。 我不知道如何限制子選擇而不包括你的限制邏輯(你的case語句)重寫為在where子句內工作。

WHERE ... AND (
    t.classification='public' OR t.classification='protected'
    OR t.id IN (SELECT rl.table_id ... rl.user_id=41026))

您編寫它的方式會有所不同,讓CASE邏輯與WHERE限制語句保持同步可能會很煩人,但它會使您的限制僅適用於匹配數據。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM