MySQL запрос - оптимизирован - PullRequest
1 голос
/ 03 апреля 2012

Можно ли выполнить эту задачу с помощью одного MySQL запроса?

Таблица urls .Поля { id , url }

1, www.mysite.kom
2, mysite.kom
3,anothersite.kom

Таблица Журналы .Поля { id , url_id , group_type - число в диапазоне 1..10}

1, 1,4
2, 1, 4
3, 2, 5
4, 2, 5
5, 3, 9

Результат запросав этом примере должно быть: 1 (mysite.com и www.mysite.com = 1)

ЦЕЛЬ:

Нужно сосчитатьвсе отдельные URL-адреса записаны в таблицу logs , но с несколькими условиями:

1) URL-адреса с префиксом www. и без него, например mysite.kom и www.mysite.kom ,
должны учитываться как 1 (не 2).

2) Имеют group_type в диапазоне 4..6

3) Теперь любой из этих URL с group_type 4..6 , которые появляются в списке с group_type ниже 4 - следует игнорировать и вообще не учитывать.

Код SQL:

SELECT COUNT(DISTINCT TRIM(LEADING 'www.' FROM b.url))
FROM logs a
INNER JOIN urls b
ON a.url_id = b.id
WHERE (group_type BETWEEN 4 AND 6) 

----- and this condition below -----

AND TRIM(LEADING 'www.' FROM b.url)
NOT IN (
  SELECT TRIM(LEADING 'www.' FROM b.url)
  FROM logs a
  INNER JOIN urls b
  ON a.url_id = b.id
  WHERE (group_type < 4)
)

Если мой sql-запрос правильный, можно ли оптимизироватьk более компактный)?

Ответы [ 2 ]

3 голосов
/ 03 апреля 2012
SELECT COUNT(DISTINCT u.id) AS COUNT_QUES FROM urls u
INNER JOIN logs l
ON u.id=l.url_id
WHERE u.url NOT IN (SELECT A.url FROM 
(SELECT * FROM urls u
WHERE SUBSTR(u.url,1,3)!='www')A,
(SELECT * FROM urls v
WHERE SUBSTR(v.url,1,3)='www')B
WHERE A.url=SUBSTR(B.url,5,LENGTH(B.url))
) 
AND l.group_type BETWEEN 4 AND 6
AND u.id NOT IN
(SELECT DISTINCT u.id FROM urls u
INNER JOIN logs l
ON u.id=l.url_id
WHERE u.url NOT IN (SELECT A.url FROM 
(SELECT * FROM urls u
WHERE SUBSTR(u.url,1,3)!='www')A,
(SELECT * FROM urls v
WHERE SUBSTR(v.url,1,3)='www')B
WHERE A.url=SUBSTR(B.url,5,LENGTH(B.url))
) 
AND l.group_type < 4
)

OR

SELECT COUNT(DISTINCT CASE WHEN B.URL_ID IS NOT NULL AND FLAG1 = 1 AND FLAG2 = 0 THEN TRIM(LEADING 'www.' FROM A.URL) END)
FROM URLS A 
LEFT JOIN (SELECT URL_ID,
           MAX(CASE WHEN GROUP_TYPE BETWEEN 4 AND 6 THEN 1 ELSE 0 END) FLAG1,
           MAX(CASE WHEN GROUP_TYPE < 4 THEN 1 ELSE 0 END) FLAG2
           FROM LOGS
           GROUP BY URL_ID) B
           ON A.ID = B.URL_ID

Надеюсь, это работает для вас. Проверьте это на SQLFIDDLE - http://sqlfiddle.com/#!2/1fde2/39

1 голос
/ 03 апреля 2012

Вот один из способов:

SELECT trimmed_url
  FROM ( SELECT TRIM(LEADING 'www.' FROM urls.url) AS trimmed_url,
                MIN(logs.group_type) AS min_group_type
           FROM logs
           JOIN urls
             ON urls.id = logs.url_id
          GROUP
             BY trimmed_url
       ) t
 WHERE min_group_type BETWEEN 4 AND 6
;

Но только вы можете судить, выглядит ли он более компактно для вас, и только тестирование может определить, работает ли оно лучше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...