Брой потребители в група, в която присъства един конкретен потребител mysql

Опитвам се да оптимизирам тази заявка, но не мога да я разбера. Всяка помощ е повече от добре дошла. Това е вътре в съхранена процедура, така че 1 се заменя с IN параметър.


Таблица userGroupRelation

userGroupID BIGINT --> външен ключ към userGroupID в таблицата на групите

userID BIGINT --> външен ключ към таблицата потребители


Таблични папки

ownerID BIGINT --> външен ключ към таблицата потребители

postersGroup BIGINT --> външен ключ към userGroupID в таблицата на групите

други неща...


SELECT folders.*,COUNT(userGroupRelation.userID) AS users
  FROM folders
LEFT JOIN userGroupRelation
  ON folders.postingGroupID = userGroupRelation.userGroupID
WHERE folders.ownerID = 1
  OR userGroupRelation.userGroupID IN (
    SELECT userGroupID FROM userGroupRelation WHERE userID = 1)
GROUP BY folders.folderID;

По принцип искам да получа всички папки, които потребителят може да види (или защото ги притежава, или защото е в група плакати за тази папка)


person Manatax    schedule 19.07.2012    source източник
comment
можете ли да публикувате структури на таблици на sqlfiddle.com   -  person Muhammad Raheel    schedule 19.07.2012


Отговори (1)


Предлагам два подхода. Единият е подобен на вашия, но премахва подзаявката и коригира клаузата COUNT. Трябва да спомена, че от въпроса ви не става ясно дали резултатът COUNT ... AS users е от значение тук, тъй като сте посочили само, че искате да получите всички папки за потребител.

SELECT 
  folders.*,
  COUNT(DISTINCT IFNULL(userGroupRelation.userID, folders.ownerID)) AS users
FROM 
  folders
  LEFT JOIN userGroupRelation ON folders.postingGroupID = userGroupRelation.userGroupID
WHERE 
  folders.ownerID = 1
  OR userGroupRelation.userID = 1
GROUP BY 
  folders.folderID
;

Това е донякъде по-добро от вашето собствено решение, тъй като подзаявката е елиминирана, но все още остава с това условие OR, което е трудно за оптимизиране -- работи на две различни таблици.

Редактиране: това следващо решение нито отговаря на въпроса, нито изобщо работи :(

Напълно различен подход е да започнете с таблицата users (ако приемем, че имате такава, разбира се):

SELECT 
  folders.*
FROM 
  users
  LEFT JOIN folders ON (folders.ownerID = users.id)
  LEFT JOIN userGroupRelation ON (userGroupRelation.userId = users.id)
  LEFT JOIN folders ON (folders.postingGroupID = userGroupRelation.userGroupID)
WHERE 
  users.id = 1
GROUP BY 
  folders.folderID
;

Този е много по-добре оптимизиран, ако имате правилни индекси на users.id и всички свързващи колони. Въпреки това:

  1. Няма да ви каже броя (други) потребители на папка
  2. SELECT filders.* .... GROUP BY filders.folderId не е строго валиден SQL -- въпреки че ще работи, ако не използвате строг sql_mode. От собственото ви запитване виждам, че не сте, така че няма да се спирам на това.
person Shlomi Noach    schedule 19.07.2012
comment
Благодаря ви за отговора. Съжалявам, че не изясних, но трябва да знам дали имам други плакати в папките и затова добавих IN (защото ако не, собственикът на папката няма да види реалното количество други плакати за него. - person Manatax; 19.07.2012
comment
Разбирам, тогава, моля, игнорирайте второто предложено решение. Също така сте прав за неуникалната таблица/псевдоним -- нямах схема/данни, върху които да работя -- следователно не можах да проверя заявката. Не само, че има неяснота - тя също не може да бъде разрешена лесно. Второто предложено решение е просто неправилно. - person Shlomi Noach; 19.07.2012