2016-09-21 5 views
0

Ich verwende Oracle und alle Indizes sind eingefügt.SQL-Leistung auf Graf Abfrage

Meine Tabellen sind unten:

CREATE TABLE users 
(user_id number(10) NOT NULL, 
    name varchar2(50) NOT NULL, 
    type_id number(10) NOT NULL, 
    is_deleted varchar2(1) NOT NULL 
); 

INSERT INTO users (user_id, name, type_id, is_deleted) VALUES (1,'John',0,'F'); 
INSERT INTO users (user_id, name, type_id, is_deleted) VALUES (2,'Mark',0,'F'); 
INSERT INTO users (user_id, name, type_id, is_deleted) VALUES (3,'Leon',0,'F'); 
INSERT INTO users (user_id, name, type_id, is_deleted) VALUES (4,'David',0,'F'); 
INSERT INTO users (user_id, name, type_id, is_deleted) VALUES (5,'Mike',0,'F'); 
INSERT INTO users (user_id, name, type_id, is_deleted) VALUES (6,'Sam',0,'F'); 
INSERT INTO users (user_id, name, type_id, is_deleted) VALUES (100,'Nike',0,'F'); 
INSERT INTO users (user_id, name, type_id, is_deleted) VALUES (200,'Adidas',0,'F'); 
INSERT INTO users (user_id, name, type_id, is_deleted) VALUES (300,'Reebook',0,'F'); 
INSERT INTO users (user_id, name, type_id, is_deleted) VALUES (400,'Puma',0,'F'); 
INSERT INTO users (user_id, name, type_id, is_deleted) VALUES (500,'Kinetix',0,'F'); 

CREATE TABLE ROLE 
(role_id number(10) NOT NULL, 
    role_name varchar2(50) NOT NULL 
); 

INSERT INTO ROLE (role_id, role_name) VALUES (10, 'User'); 
INSERT INTO ROLE (role_id, role_name) VALUES (11, 'Company'); 

CREATE TABLE ROLE_REL 
(id number(10) NOT NULL, 
    user_id number(10) NOT NULL, 
    role_id number(10) NOT NULL 
); 

INSERT INTO role_rel (id,user_id,role_id) VALUES (1,1, 10); 
INSERT INTO role_rel (id,user_id,role_id) VALUES (2,2, 10); 
INSERT INTO role_rel (id,user_id,role_id) VALUES (3,3, 10); 
INSERT INTO role_rel (id,user_id,role_id) VALUES (4,4, 10); 
INSERT INTO role_rel (id,user_id,role_id) VALUES (5,5, 10); 
INSERT INTO role_rel (id,user_id,role_id) VALUES (6,6, 10); 
INSERT INTO role_rel (id,user_id,role_id) VALUES (7,100, 11); 
INSERT INTO role_rel (id,user_id,role_id) VALUES (8,200, 11); 
INSERT INTO role_rel (id,user_id,role_id) VALUES (9,300, 11); 
INSERT INTO role_rel (id,user_id,role_id) VALUES (10,400, 11); 
INSERT INTO role_rel (id,user_id,role_id) VALUES (11,500, 11); 

CREATE TABLE COMPANY_USER 
(id number(10) NOT NULL, 
    user_id number(10) NOT NULL, 
    company_id number(10) NOT NULL, 
    is_deleted varchar2(1) NOT NULL 
); 

INSERT INTO company_user(id,user_id,company_id,is_deleted) VALUES (1,1,100,'F'); 
INSERT INTO company_user(id,user_id,company_id,is_deleted) VALUES (2,1,200,'F'); 
INSERT INTO company_user(id,user_id,company_id,is_deleted) VALUES (3,1,300,'F'); 
INSERT INTO company_user(id,user_id,company_id,is_deleted) VALUES (4,3,400,'F'); 
INSERT INTO company_user(id,user_id,company_id,is_deleted) VALUES (5,1,500,'F'); 
INSERT INTO company_user(id,user_id,company_id,is_deleted) VALUES (6,2,100,'F'); 
INSERT INTO company_user(id,user_id,company_id,is_deleted) VALUES (7,3,100,'F'); 
INSERT INTO company_user(id,user_id,company_id,is_deleted) VALUES (8,4,100,'F'); 
INSERT INTO company_user(id,user_id,company_id,is_deleted) VALUES (9,4,200,'F'); 
INSERT INTO company_user(id,user_id,company_id,is_deleted) VALUES (10,5,100,'F'); 
INSERT INTO company_user(id,user_id,company_id,is_deleted) VALUES (11,6,100,'F'); 
INSERT INTO company_user(id,user_id,company_id,is_deleted) VALUES (12,6,200,'F'); 

CREATE TABLE CITY 
(id number(10) NOT NULL, 
    city_name varchar2(50) NOT NULL 
); 

INSERT INTO city(id,city_name) VALUES (1,'New York'); 
INSERT INTO city(id,city_name) VALUES (2,'Sacramento'); 
INSERT INTO city(id,city_name) VALUES (3,'Washington'); 
INSERT INTO city(id,city_name) VALUES (4,'New Jersey'); 
INSERT INTO city(id,city_name) VALUES (5,'Toronto'); 

CREATE TABLE CITY_USER 
(id number(10) NOT NULL, 
    user_id number(10) NOT NULL, 
    city_id number(10) NOT NULL, 
    is_deleted varchar2(1) NOT NULL 
); 

INSERT INTO CITY_USER(id,user_id,city_id,is_deleted) VALUES (1,1,3,'F'); 
INSERT INTO CITY_USER(id,user_id,city_id,is_deleted) VALUES (2,2,4,'F'); 
INSERT INTO CITY_USER(id,user_id,city_id,is_deleted) VALUES (3,3,4,'F'); 
INSERT INTO CITY_USER(id,user_id,city_id,is_deleted) VALUES (4,4,1,'F'); 
INSERT INTO CITY_USER(id,user_id,city_id,is_deleted) VALUES (5,5,1,'F'); 
INSERT INTO CITY_USER(id,user_id,city_id,is_deleted) VALUES (6,6,2,'F'); 
INSERT INTO CITY_USER(id,user_id,city_id,is_deleted) VALUES (7,1,1,'F'); 

CREATE TABLE BRANCH 
(id number(10) NOT NULL, 
    branch_name varchar2(50) NOT NULL 
); 

INSERT INTO branch(id,branch_name) VALUES (1,'Black'); 
INSERT INTO branch(id,branch_name) VALUES (2,'White'); 
INSERT INTO branch(id,branch_name) VALUES (3,'Blue'); 
INSERT INTO branch(id,branch_name) VALUES (4,'Yellow'); 
INSERT INTO branch(id,branch_name) VALUES (5,'Orange'); 

CREATE TABLE BRANCH_USER(
id number(10) NOT NULL, 
user_id number(10) NOT NULL, 
branch_id number(10) NOT NULL, 
is_deleted varchar2(1) NOT NULL 
); 

INSERT INTO BRANCH_USER(id,user_id,branch_id,is_deleted) VALUES (1,1,5,'F'); 
INSERT INTO BRANCH_USER(id,user_id,branch_id,is_deleted) VALUES (2,2,1,'F'); 
INSERT INTO BRANCH_USER(id,user_id,branch_id,is_deleted) VALUES (3,3,1,'F'); 
INSERT INTO BRANCH_USER(id,user_id,branch_id,is_deleted) VALUES (4,4,2,'F'); 
INSERT INTO BRANCH_USER(id,user_id,branch_id,is_deleted) VALUES (5,5,3,'F'); 
INSERT INTO BRANCH_USER(id,user_id,branch_id,is_deleted) VALUES (6,6,3,'F'); 
INSERT INTO BRANCH_USER(id,user_id,branch_id,is_deleted) VALUES (7,1,1,'F'); 
INSERT INTO BRANCH_USER(id,user_id,branch_id,is_deleted) VALUES (8,2,3,'F'); 
INSERT INTO BRANCH_USER(id,user_id,branch_id,is_deleted) VALUES (9,1,3,'F'); 

Unter meiner Anfrage ist.

SELECT count(CU.company_ID) as TypeID, CU.Company_ID, C.Name 
FROM Company_User CU 
INNER JOIN USERS C 
on CU.Company_ID = c.user_ID 
INNER JOIN (SELECT Distinct U.user_ID 
    FROM users U 
    INNER JOIN Role_Rel RR 
    on RR.user_ID = U.user_ID 
    WHERE U.is_deleted = 'F' 
    and RR.Role_ID = 10) U 
on CU.User_ID = U.user_ID 
INNER JOIN (SELECT Distinct PU.user_ID 
    FROM users PU 
    INNER JOIN city_user SUL 
    on SUL.user_ID = PU.user_ID 
    WHERE sul.city_id = 1 and PU.is_deleted = 'F') PU 
    on CU.User_ID = PU.user_ID 
INNER JOIN (SELECT Distinct KU.user_ID 
    FROM users KU 
    INNER JOIN branch_user hd 
    on hd.user_ID = KU.user_ID 
    WHERE hd.branch_id = 3 and KU.is_deleted = 'F' and hd.is_deleted = 'F') KU 
    on CU.User_ID = KU.user_ID 
GROUP BY CU.Company_Id, C.Name 
ORDER BY count(CU.Company_ID) Desc; 

Mein Ergebnis ist, wie ich will, Unternehmen sind als ihre Benutzer zählen Anzahl aufgeführt.

TypeID Company_id  Name 
6   100   Nike 
3   200   Adidas 
2   400   Puma 
1   300   Reebok. 

Mein Ergebnis

TYPEID COMPANY_ID NAME 
2  100   Nike 
1  500   Kinetix 
1  200   Adidas 
1  300   Reebook 

SQL-FIDDLE is here.

Ich bearbeitet meine Frage nach @ xQbert Antwort und ich füge zwei neue Einschränkung in Abfrage nach Branch_user und city_user Tabellen. Wie kann ich meine Frage ändern, um besser zu funktionieren?

Stellen Sie sich vor, alle benötigten Indizes werden hinzugefügt. Ich bin offen für neue Abfrage oder neue benötigte Indizes, die in Abfrage sein sollten. Abfrage löst mein Problem, nur um meine Abfrage zu optimieren.

Vielen Dank im Voraus.

+2

Welche DBMS verwenden Sie? –

+0

Ich benutze Oracle. Ich werde jetzt meine Frage bearbeiten. –

+0

Hinzufügen von Tabellen- und Indexdefinitionen usw. Ausführungsplan/erklären? – jarlh

Antwort

2

Ohne Indexe, Ausführungsplan und Tabellenstatistiken, die nicht verbessert werden können, verfügen wir nicht über die erforderlichen Informationen zur Auswertung. Einfach gesagt, die Frage fehlt die Analyse oder Informationen zu wissen, welche Verbesserungen zutreffen.

Ich würde wahrscheinlich es auf diese Weise geschrieben habe ...

Kann nicht sagen, wenn es aber nicht schneller oder führt zu einem besseren Ausführungsplan ist.

SELECT count(CU.company_ID) as TypeID, CU.Company_ID, C.Name 
FROM Company_User CU 
INNER JOIN Company C 
on CU.Company_ID = c.Company_ID 
INNER JOIN (SELECT Distinct U.user_ID 
      FROM users U 
      INNER JOIN Role_Rel RR 
       on RR.user_ID = U.user_ID 
      WHERE U.deleted = 'F' 
       and RR.Role_ID = 10) U 
on CU.User_ID = U.user_ID 
GROUP BY CU.Company_Id, C.Name 
ORDER BY count(CU.Company_ID) Desc; 
+0

Das 'select' in der Spaltenliste war ein großes mögliches Leistungsproblem, das diese Antwort korrigiert. – Allan

+1

Einverstanden, aber auf einem kleinen Datensatz denke ich nicht, dass wir viel Leistungsunterschied sehen würden. Indem wir es entfernen, eliminieren wir grundsätzlich einen iterativen Aufruf von select, um jeden Namen abzuleiten, und erlauben der Datenbank in satzbasierten Operationen zu operieren, was einen einzelnen Join anstelle von mehreren select-Anweisungen ermöglicht. – xQbert

+0

@xQbert Ich habe Unternehmen und Benutzer Tabelle kombiniert, und neue Rolle in Rollentabellen, wie Ihre Abfrage könnte nach dieser neuen Änderung neu geschrieben werden? –

0

Sie wollen Unternehmen mit ihren unterschiedlichen Benutzerzahlen? Wählen Sie dann aus den Benutzern aus und verbinden Sie die Benutzeranzahl.

select 
    c.company_id, 
    c.companyname, 
    cu.users 
from company c 
join 
(
    select company_id, count(distinct user_id) as users 
    from company_user 
    where user_id in (select user_id from role_rel where role_id = 10) 
    and user_id in (select user_id from users where deleted = 'F') 
    group by company_id 
) cu on cu.company_id = c.company_id 
order by cu.users desc; 

Okay, kein Unternehmen Tabelle mehr ...

select 
    c.user_id as company_id, 
    c.name as companyname, 
    cu.users 
from 
(
    select * 
    from users 
    where user_id in (select user_id from role_rel where role_id = 11) 
    and deleteted = 'F' 
) c 
join 
(
    select company_id, count(distinct user_id) as users 
    from company_user 
    where user_id in 
    (
    select user_id 
    from users 
    where user_id in (select user_id from role_rel where role_id = 10) 
    and deleteted = 'F' 
) 
    group by company_id 
) cu on cu.company_id = c.company_id 
order by cu.users desc; 

Sie mit Klauseln verwenden können, statt direkt abgeleitete Tabellen, wenn Sie möchten, dass besser:

with company_data as 
(
    select * 
    from users 
    where user_id in (select user_id from role_rel where role_id = 11) 
    and deleteted = 'F' 
) 
, user_data as 
(
    select * 
    from users 
    where user_id in (select user_id from role_rel where role_id = 10) 
    and deleteted = 'F' 
) 
... 
0

Versuchen Sie diese Version mit Unterabfragen:

SELECT 
    count(DISTINCT user_id) AS type_id, 
    company_id AS id, 
    (
    SELECT name 
    FROM users 
    WHERE user_id = com_user.company_id 
) AS name 
FROM company_user com_user 
WHERE 1=1 
    -- check that "user_id" is associated 
    -- with role named "User" and this user 
    -- was not deleted 
    AND user_id IN 
    (
    SELECT user_id 
    FROM users 
    WHERE 1=1 
     AND deleted = 'F' 
     AND user_id IN 
     (
     SELECT user_id 
     FROM role_rel 
     WHERE role_id IN (SELECT id FROM role WHERE roleName = 'User') 
    ) 
) 
    -- check that "company_id" is associated 
    -- with role named "Company" and this user 
    -- was not deleted 
    AND company_id IN 
    (
    SELECT user_id 
    FROM users 
    WHERE 1=1 
     AND deleted = 'F' 
     AND user_id IN 
     (
     SELECT user_id 
     FROM role_rel 
     WHERE role_id IN (SELECT id FROM role WHERE roleName = 'Company') 
    ) 
) 
GROUP BY company_id 
ORDER BY count(company_id) DESC 
; 

Ich mag nicht so viel von der Abfrage der Spalte name mit Unterabfrage, aber ich werde versuchen, es später zu ändern, wenn diese Abfrage nicht gut für Sie funktioniert.