Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
Самоучитель PHP 5 / 6 (3 издание). Авторы: Кузнецов М.В., Симдянов И.В. PHP на примерах (2 издание). Авторы: Кузнецов М.В., Симдянов И.В. Социальная инженерия и социальные хакеры. Авторы: Кузнецов М.В., Симдянов И.В. MySQL 5. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В. MySQL на примерах. Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум MySQL

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: вытащить уникальные записи
 
 автор: P@Sol   (22.08.2012 в 17:06)   письмо автору
 
 

1. таблица data
data_id res_id info date
1 1 тест1 2011-09-19 18:27:18
2 1 тест2 2011-09-19 17:28:35
3 1 тест1 2011-09-19 16:28:35
4 2 тест2 2011-09-19 15:30:35
5 3 тест1 20-11-09-19 14:00:00

2. таблица res
res_id user_id
1 1
2 2
3 3

3. таблица user
user_id user_name
1 Ваня
2 Слава
3 Таня

4. таблица value
value_id data_id info value
1 1 показатель 1 10
2 1 показатель 2 20
3 2 показатель 3 143
5 3 показатель 1 23
6 3 показатель 2 25
7 4 показатель 3 123
8 5 показатель 1 17
9 5 показатель 2 30


В итоге надо получить:
Всего человек, прошедший "тест 1" с "показатель 1" от 1 до 15 - 1 шт.
при смене параметров
Всего человек, прошедший "тест 1" с "показатель 1" от 15 до 35 - 1 шт.

если в таблице data тест проводился больше 1 раза, надо брать последний.

  Ответить  
 
 автор: P@Sol   (22.08.2012 в 17:19)   письмо автору
 
   для: P@Sol   (22.08.2012 в 17:06)
 

навоял такой запрос:

<?
select count
(distinct user_idfrom (SELECT user_id,  valuedate FROM res as Rdata
as Dvalue as RV where R.res_id D.res_id and D.info 'тест1' and 
D.data_id RV.data_id and RV.info'показатель 1' order by R.user_idD.date desc) as Count where Count.value >= and Count.value<=14;


выводит общее кол-во правильно (если убрать where), а при where неправильно определяет уникальные записи (не всегда выбирает самую последнюю)

  Ответить  
 
 автор: Sfinks   (22.08.2012 в 20:48)   письмо автору
 
   для: P@Sol   (22.08.2012 в 17:06)
 

SELECT count(*)co
FROM (SELECT * FROM `value` WHERE `info`='показатель 1' AND `value` BETWEEN 1 AND 14)v
JOIN (SELECT * FROM `data` WHERE `info`='тест 1')d ON v.data_id = d.data_id
JOIN res ON res.res_id = d.res_id
GROUP BY user_id
SELECT count(*)co
FROM (SELECT * FROM `value` WHERE `info`='показатель 1' AND `value` BETWEEN 15 AND 34)v
JOIN (SELECT * FROM `data` WHERE `info`='тест 1')d ON v.data_id = d.data_id
JOIN res ON res.res_id = d.res_id
GROUP BY user_id

  Ответить  
 
 автор: P@Sol   (23.08.2012 в 09:38)   письмо автору
 
   для: Sfinks   (22.08.2012 в 20:48)
 

тажа ошибка, что и в моем запросе. Во втором случае он выводит 2 человек, вместо 1

Получается что в первом случае выводит 1 человека, во втором - 2. Всего 3 получается, а на самом то деле (как я писал выше), тестирования всего 2 должно учитываться

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

  Ответить  
 
 автор: Sfinks   (23.08.2012 в 10:59)   письмо автору
 
   для: P@Sol   (23.08.2012 в 09:38)
 

Почему должно быть 1?
На приведенных выше данных 2 пользователя прошли "тест 1" с "показатель 1" от 15 до 35.
Это Ваня с value 23 и Таня с value 17.
Если это не так, объясните кого из них вы хотите отсеить и по какому признаку. Я пока не могу понять.
____________________
Сообразил.... Ща придумаю.....

  Ответить  
 
 автор: Sfinks   (23.08.2012 в 12:01)   письмо автору
 
   для: Sfinks   (23.08.2012 в 10:59)
 

/*<?*/
SELECT count(*) FROM value
WHERE info
='показатель 1'
  
AND value BETWEEN 15 AND 34
  
AND data_id INSELECT SELECT data_id FROM data JOIN res USING(res_id)
                           
WHERE user_id=t.ui AND date=t.dt )
                  
FROMSELECT user_id uimax(date)dt
                        FROM data d JOIN res r USING
(res_id)
                        
WHERE info 'тест1'
                        
GROUP BY user_id
                  
)t
                
)

  Ответить  
 
 автор: P@Sol   (23.08.2012 в 14:06)   письмо автору
 
   для: Sfinks   (23.08.2012 в 12:01)
 

жесть! спасибо

---
жалко, что время обработки порядка 10 секунд

  Ответить  
 
 автор: Sfinks   (23.08.2012 в 16:20)   письмо автору
 
   для: P@Sol   (23.08.2012 в 14:06)
 

>жалко, что время обработки порядка 10 секунд
А Вы уверены, что нужна такая сложная система замутов с таблицами?
Например если в таблице res дублирования user_id не может быть, то ее можно объеденить с таблицей user, а в data сделать связь не по res_id, а по user_id. Это значительно облегчило бы запрос.

Кстати, в мускуле есть какой-то баг с оператором IN. Раньше уже замечал это. Я попробую переписать через EXISTS....

  Ответить  
 
 автор: Sfinks   (23.08.2012 в 16:51)   письмо автору
 
   для: Sfinks   (23.08.2012 в 16:20)
 

Проверьте такой вариант:
/*<?*/
SELECT count(*)co
FROM
SELECT user_id uimax(date)dt
      FROM data JOIN res USING
(res_id)
      
WHERE info 'тест1'
      
GROUP BY user_id
)t
JOIN data d ON date 
dt
JOIN res r ON user_id 
ui AND d.res_id r.res_id
JOIN value v ON v
.info='показатель 1' AND v.data_id d.data_id AND value BETWEEN 15 AND 34
Должен быть сильно быстрее.

Но все же подумайте об упрощении схемы БД.

  Ответить  
 
 автор: P@Sol   (23.08.2012 в 18:21)   письмо автору
 
   для: Sfinks   (23.08.2012 в 16:20)
 

<?
SELECT count
(*) FROM res as RV
JOIN 
(SELECT SELECT DATA_ID FROM data JOIN res USING(RES_ID
                           
WHERE USER_ID=t.ui AND DATE=t.dt )  data2
                  FROM
SELECT USER_ID uimax(DATEdt 
                        FROM data d JOIN res r USING
(RES_ID
                        
WHERE INFO 'тест1' 
                        
GROUP BY USER_IDtdata
         on RV
.DATA_ID=data.data2   AND INFO'показатель1' 
  
AND VALUE BETWEEN 1 AND 14


у меня такой код работает порядка 1 секунды)

  Ответить  
 
 автор: Sfinks   (23.08.2012 в 21:53)   письмо автору
 
   для: P@Sol   (23.08.2012 в 18:21)
 

Может все-таки
SELECT count(*) FROM value
а не
SELECT count(*) FROM res
?
______________________
По сути это тоже самое, что мой пост от (23.08.2012 в 12:01). Я же и говорю - IN гонит.
______________________
Вы вариант от (23.08.2012 в 16:51) проверяли? Он должен быть быстрее.

  Ответить  
 
 автор: P@Sol   (24.08.2012 в 09:38)   письмо автору
 
   для: Sfinks   (23.08.2012 в 21:53)
 

1. да value
2. да, был взят за основу ваш скрипт и проведен эксперемент по увеличению скорости, по интуиции подумал, что дело в IN
3. мой вариант и Ваш последний соизмеримы по скорости - 0,156 оба показали

------
4. Возникла проблемка. У одного человека оказалась, что есть две записи в data, но нет записи в таблице value для последнего теста и он получается нигде не учтен. (вместо 1071 человека показывается 1070 человек). Соответственно в данном случае надо взять не последний тест, а последний, где есть показатель1

  Ответить  
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования