2016-11-26 28 views
3

我想讓我的Flarum論壇在人工干預數據庫後更新其討論記錄。 (Flarum仍處於測試階段,仍然缺乏許多功能,做手工修理東西是不是罕見的。)我設法組成以下查詢該做什麼,我想:簡化UPDATE語句中的多個子查詢

UPDATE discussions as d SET 
    d.start_time = 
    (SELECT min(p.time) FROM posts as p 
     WHERE p.discussion_id = d.id), 
    d.last_time = 
    (SELECT max(p.time) FROM posts as p 
     WHERE p.discussion_id = d.id), 
    d.comments_count = 
    (SELECT count(*) FROM posts as p 
     WHERE p.discussion_id = d.id AND p.type = 'comment'), 
    d.participants_count = 
    (SELECT count(DISTINCT p.user_id) FROM posts as p 
     WHERE p.discussion_id = d.id), 
    d.start_post_id = 
    (SELECT p.id FROM posts as p 
     WHERE p.discussion_id = d.id 
     ORDER BY p.number ASC LIMIT 1), 
    d.start_user_id = 
    (SELECT p.user_id FROM posts as p 
     WHERE p.discussion_id = d.id 
     ORDER BY p.number ASC LIMIT 1), 
    d.last_post_id = 
    (SELECT p.id FROM posts as p 
     WHERE p.discussion_id = d.id 
     ORDER BY p.number DESC LIMIT 1), 
    d.last_post_number = 
    (SELECT p.number FROM posts as p 
     WHERE p.discussion_id = d.id 
     ORDER BY p.number DESC LIMIT 1), 
    d.last_user_id = 
    (SELECT p.user_id FROM posts as p 
     WHERE p.discussion_id = d.id 
     ORDER BY p.number DESC LIMIT 1); 

,但它看起來很醜陋。我確信有一種方法可以用更加簡潔和高效的方式編寫相同的邏輯,但我並不是真正意識到如何去做SQL。有人能告訴我如何消除這些幾乎重複的子查詢?

上述的表的定義是以下的(與某些細節省略):

CREATE TABLE discussions (
    id     int unsigned NOT NULL AUTO_INCREMENT, 
    title    varchar(200) NOT NULL, 
    comments_count  int(10) unsigned NOT NULL DEFAULT '0', 
    participants_count int(10) unsigned NOT NULL DEFAULT '0', 
    number_index   int(10) unsigned NOT NULL DEFAULT '0', 
    start_time   datetime NOT NULL, 
    start_user_id  int(10) unsigned DEFAULT NULL, 
    start_post_id  int(10) unsigned DEFAULT NULL, 
    last_time   datetime DEFAULT NULL, 
    last_user_id   int(10) unsigned DEFAULT NULL, 
    last_post_id   int(10) unsigned DEFAULT NULL, 
    last_post_number  int(10) unsigned DEFAULT NULL, 
    ...); 

CREATE TABLE posts (
    id     int(10) unsigned NOT NULL AUTO_INCREMENT, 
    discussion_id  int(10) unsigned NOT NULL, 
    number    int(10) unsigned DEFAULT NULL, 
    time     datetime NOT NULL, 
    user_id    int(10) unsigned DEFAULT NULL, 
    type     varchar(100) DEFAULT NULL, 
    ...); 

Flarum使用MySQL作爲其主要存儲後端,所以MySQL特定溶液就可以了。但是,如果有人知道如何解決ANSI-SQL中的問題,那將會很棒。

+0

沒有捷徑,你想要什麼。只有我想,你必須這樣做。但我很想看看它是否會發生。 – FallAndLearn

回答

1

你可以使用一個內部連接,並使用最大值和最小值的第一個和最後

UPDATE discussions as d 
INNER JOIN posts as p on d.id = p.discussion_id 
SET d.start_time = min(p.time), 
    d.last_time = max(p.time), 
    d.comments_count = count(*), 
    d.participants_count = count(DISTINCT p.user_id) , 
    d.start_post_id = min(p.id), 
    d.start_user_id = min(p.user_id ), 
    d.last_post_id = max( p.id), 
    d.last_post_number = max(p.number), 
    d.last_user_id = max(p.user_id ), 
    d.comments_count = sum(case when p.type = 'comment' then 1 else 0) 
GROUP BY d.id 
+0

我認爲它不會按要求工作。首先,你正在改變表'討論'的模式 – FallAndLearn

+0

我已經改變了nothings ..我只是重構了查詢使用.. SQL功能..如OP – scaisEdge

+0

需要看起來很有前途!但是我不明白'd.last_post_id = min(d.last_post_id)'會在這裏工作。 MySQL問題*「錯誤:無效使用組功能」*有關它的消息。 – firegurafiku