|
|
|
| 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:06)
| | навоял такой запрос:
<?
select count(distinct user_id) from (SELECT user_id, value, date FROM res as R, data
as D, value 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_id, D.date desc) as Count where Count.value >= 1 and Count.value<=14;
|
выводит общее кол-во правильно (если убрать where), а при where неправильно определяет уникальные записи (не всегда выбирает самую последнюю) | |
|
|
|
|
|
|
|
для: 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
|
| |
|
|
|
|
|
|
|
для: Sfinks
(22.08.2012 в 20:48)
| | тажа ошибка, что и в моем запросе. Во втором случае он выводит 2 человек, вместо 1
Получается что в первом случае выводит 1 человека, во втором - 2. Всего 3 получается, а на самом то деле (как я писал выше), тестирования всего 2 должно учитываться
----
т.е. сначало надо выбрать таблицу с уникальными пользователями с последними тестами, а потом из нее уже выбирать в нужом диапазоне. А не сначало выбирать в диапазоне, а потом отсеивать уникальные записи. | |
|
|
|
|
|
|
|
для: P@Sol
(23.08.2012 в 09:38)
| | Почему должно быть 1?
На приведенных выше данных 2 пользователя прошли "тест 1" с "показатель 1" от 15 до 35.
Это Ваня с value 23 и Таня с value 17.
Если это не так, объясните кого из них вы хотите отсеить и по какому признаку. Я пока не могу понять.
____________________
Сообразил.... Ща придумаю..... | |
|
|
|
|
|
|
|
для: Sfinks
(23.08.2012 в 10:59)
| |
/*<?*/
SELECT count(*) FROM value
WHERE info='показатель 1'
AND value BETWEEN 15 AND 34
AND data_id IN( SELECT ( SELECT data_id FROM data JOIN res USING(res_id)
WHERE user_id=t.ui AND date=t.dt )
FROM( SELECT user_id ui, max(date)dt
FROM data d JOIN res r USING(res_id)
WHERE info = 'тест1'
GROUP BY user_id
)t
)
|
| |
|
|
|
|
|
|
|
для: Sfinks
(23.08.2012 в 12:01)
| | жесть! спасибо
---
жалко, что время обработки порядка 10 секунд | |
|
|
|
|
|
|
|
для: P@Sol
(23.08.2012 в 14:06)
| | >жалко, что время обработки порядка 10 секунд
А Вы уверены, что нужна такая сложная система замутов с таблицами?
Например если в таблице res дублирования user_id не может быть, то ее можно объеденить с таблицей user, а в data сделать связь не по res_id, а по user_id. Это значительно облегчило бы запрос.
Кстати, в мускуле есть какой-то баг с оператором IN. Раньше уже замечал это. Я попробую переписать через EXISTS.... | |
|
|
|
|
|
|
|
для: Sfinks
(23.08.2012 в 16:20)
| | Проверьте такой вариант:
/*<?*/
SELECT count(*)co
FROM( SELECT user_id ui, max(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
| Должен быть сильно быстрее.
Но все же подумайте об упрощении схемы БД. | |
|
|
|
|
|
|
|
для: 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 ui, max(DATE) dt
FROM data d JOIN res r USING(RES_ID)
WHERE INFO = 'тест1'
GROUP BY USER_ID) t) data
on RV.DATA_ID=data.data2 AND INFO= 'показатель1'
AND VALUE BETWEEN 1 AND 14
|
у меня такой код работает порядка 1 секунды) | |
|
|
|
|
|
|
|
для: 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) проверяли? Он должен быть быстрее. | |
|
|
|
|
|
|
|
для: Sfinks
(23.08.2012 в 21:53)
| | 1. да value
2. да, был взят за основу ваш скрипт и проведен эксперемент по увеличению скорости, по интуиции подумал, что дело в IN
3. мой вариант и Ваш последний соизмеримы по скорости - 0,156 оба показали
------
4. Возникла проблемка. У одного человека оказалась, что есть две записи в data, но нет записи в таблице value для последнего теста и он получается нигде не учтен. (вместо 1071 человека показывается 1070 человек). Соответственно в данном случае надо взять не последний тест, а последний, где есть показатель1 | |
|
|
|