2016-10-15 81 views
1

我有我想查詢以下數據庫表:查詢所有

t_shared_users 
user_id 
user_category 
folder_id 
expiry 

t_documents 
id 
folder_id 
user_id 
user_category 
description 
created 
updated 

t_folder 
id 
type 
user_id 
user_category 
created 
updated 

我想找到所有你自己,並共享訪問的文檔。即。搜索t_documents中的所有文檔,其中user_id = 1 AND user_category = 100,但也包括那些文檔在t_shared_users中有權訪問的文件夾中。這是我在查詢的嘗試:

SELECT 
    id, 
    folder_id, 
    user_id, 
    user_category, 
    description, 
    created, 
    updated 
    FROM 
    t_documents 
    WHERE 
    user_category = 100 
    AND user_id = 1 

    UNION ALL 

    SELECT 
    d.id, 
    d.folder_id, 
    d.user_id, 
    d.user_category, 
    d.description, 
    d.created, 
    d.updated 
    FROM 
    t_documents d 
    JOIN 
    t_shared_users s 
    ON 
    d.folder_id = s.folder_id 
    WHERE 
    d.user_category = 100 
    d.AND user_id = 1 

ORDER BY 
    created ASC 
LIMIT 
    10 

是否有任何更好/更高性能/簡潔的方式來編寫此查詢?以上看起來有點冗長和緩慢。

編輯:

CREATE TABLE t_folder (
    id   SERIAL     NOT NULL, 
    user_category SMALLINT     NOT NULL, 
    user_id  INTEGER     NOT NULL, 
    type   INTEGER     NOT NULL, 
    description TEXT, 
    created  TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), 
    updated  TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), 
    PRIMARY KEY (id) 
); 

CREATE TABLE t_documents (
    id   BIGSERIAL    NOT NULL, 
    folder_id  INTEGER, 
    user_category SMALLINT     NOT NULL, 
    user_id  INTEGER     NOT NULL, 
    description TEXT      NOT NULL, 
    created  TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), 
    updated  TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), 
    PRIMARY KEY (id) 
); 

CREATE TABLE t_shared_users (
    id   SERIAL, 
    folder_id  INTEGER     NOT NULL, 
    user_category INTEGER     NOT NULL, 
    user_id  INTEGER     NOT NULL, 
    expiry  TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), 
    PRIMARY KEY (id) 
); 
+0

請訪問http://元。 stackoverflow.com/questions/333952/why-should-i-provide-an-mcve-for-what-seems-to-me-to-be-a-very-simple-sql-query – Strawberry

+0

@Strawberry我很想念如果有可能會有相同效果的高效/聰明JOIN環? –

+0

和我一樣,當我運行「解釋分析」命令時,我會得到一個較小的上限成本。現在,它如下所示:追加(成本= 0.57..749.08行= 282寬度= 36)(實際時間= 0.024..0.047行= 3循環= 1) –

回答

1

這是您的查詢:

SELECT 
    id, 
    folder_id, 
    user_id, 
    user_category, 
    description, 
    created, 
    updated 
    FROM 
    t_documents 
    WHERE 
    user_category = 100 
    AND user_id = 1 

    UNION ALL 

    SELECT 
    d.id, 
    d.folder_id, 
    d.user_id, 
    d.user_category, 
    d.description, 
    d.created, 
    d.updated 
    FROM 
    t_documents d 
    JOIN 
    t_shared_users s 
    ON 
    d.folder_id = s.folder_id 
    WHERE 
    d.user_category = 100 
    AND d.user_id = 1 -- your query actually has a typo here 

我不理解上面的查詢是什麼,爲什麼你在查詢的底部與過濾d.user_categoryd.user_idt_documents表)。你確定你不是指s.user_categorys.user_idt_shared_users)?如果不是,加入t_shared_users有什麼意義?

假設我是正確的,你的查詢是錯誤的,這是我會怎麼把它改寫:

select d.* 
    from t_documents d 
where d.user_category = 100 
    and d.user_id = 1 
union 
select d.* 
    from t_shared_users s 
    join t_documents d 
    on d.folder_id = s.folder_id 
where s.user_category = 100 
    and s.user_id = 1 

請注意,我用union代替union all,因爲我相信這是技術上可以得到可能不需要否則重複文件。

而且,只是作爲一個粗略的估計,這些都是我會定義良好的性能指標:

  • t_documents (user_id, user_category)
  • t_documents (folder_id)
  • t_shared_users (user_id, user_category, folder_id)
+0

您認爲t_shared_users將這些索引拆分爲兩個更好嗎?即。一個僅用於folder_id,另一個用於user_id,user_category?這是我目前的。 –

+0

另外,您何時會認爲UNION ALL可能會發生重複?使用UNION和UNION ALL之間的性能差異並非微不足道。我對t_shared_users btw有這個約束:CONSTRAINT constraint_user_per_doc UNIQUE(user_category,user_id,folder_id) –

+1

關於您的索引問題:我認爲您當前的拆分索引應該提供可接受的性能。但我認爲將'folder_id'添加到'user_id,user_category'索引應該允許有更好的執行計劃。你必須嘗試一下,看看它實際產生了多大的差異。關於重複的可能性:我不知道您的業務規則,但是如果文檔既可以由用戶'1'擁有,也可以同時成爲共享給用戶的文件夾的一部分' 1',那麼'union all'會將該文件返回兩次。 '工會'會解決這個問題。 – sstan

-1

從查詢開始,你給了,我會left join

select 
    d.id, 
    d.folder_id, 
    d.user_id, 
    d.user_category, 
    d.description, 
    d.created, 
    d.updated 
from t_documents d 
left join t_shared_users s on d.folder_id = s.folder_id 
where (d.user_category = 100 and d.user_id = 1) 
     or (s.user_category = 100 and s.user_id = 1) 

這將使你從t_documents與USER_ID = 1和user_category =所有條目替換join 100以及所有具有相同where子句的條目,您可以在其中訪問共享文檔。

+0

當我沒有在where子句中指定表時,出現錯誤 「錯誤:列引用」user_category「不明確。」如果我要選擇d.user_type或s.user_type,則查詢將是錯誤的 –

+0

然後,您提供的查詢必須提供相同的錯誤。 –

+0

是的,我只注意到了這個錯字。鑑於上面的查詢,有沒有一種方法來調整你的答案來簡化它? –