|
|
|
| есть 2 таблицы: в одной предложения, в другой связанные с ним количество голосов за и против. Структура:
table1
id int(11) unsigned NOT NULL auto_increment
name varchar(20) NOT NULL
table2
id int(11) unsigned NOT NULL auto_increment
golos tinyint(1) NOT NULL
несущественные в данном случае поля я просто удалил из описания. Таблицы связаны по полю id.
В поле голос заносится либо 1 (за), либо 2 (против). Количество записей в table2 с одинаковым id определяется числом голосовавших. Таким образом, количество голосов за или против, можно определить как count(*) WHERE golos=1 или count(*) WHERE golos=2.
Нужно вывести список предложений и количество голосов за и против, вроде такого:
Предложение | За | Против
--------------------------------------------------------------------------------------------
пить пиво | 2 | 3
пить кофе | 3 | 2
плюнуть на все и разойтись по домам | 1 | 0
|
Запрос получается вроде такого:
SELECT name,IFNULL(za,0) AS za,IFNULL(protiv,0) AS protiv
FROM table1 AS t1
LEFT JOIN (SELECT id, COUNT(id) AS za FROM table2 WHERE golos=1 GROUP BY id) AS t2 ON t2.id=t1.id
LEFT JOIN (SELECT id, COUNT(id) AS za FROM table2 WHERE golos=2 GROUP BY id) AS t3 ON t3.id=t1.id
|
Вопрос такой: не лучше ли разделить "за" и "против" на разные поля, чтоб потом выбирать:
SELECT name,za,protiv
FROM table1 AS t1
LEFT JOIN table2 AS t2 ON t2.id=t1.id
GROUP BY t1.id
|
В этом случае усложняется запись в базу, так как нужно определиться, в какое поле писать: за, или против (в первом пишется в единственное поле результата). Но, возможно, во втором случае выборка будет происходить значительно быстрее. По крайней мере запрос выглядит значительно компактней
Нужно мнение, исходящее из практического опыта. Ввести 100 000 записей и протестить результат я, конечно, могу. Но не хочется тратить на это целый день. Так что, прошу мнение специалистов.
П.С. Изначально данные приходят из формы:
<input type=radio name='golos' value='0'>Воздержался
<input type=radio name='golos' value='1'>Да
<input type=radio name='golos' value='2'>Нет
Соответственно запись данных:
INSERT INTO table2 (id,golos) VALUES (".$_POST['id'].",".quote_smart(@$_POST['golos'])
Но можно и так (если писать в разные поля):
<input type=radio name='no' value=''>Воздержался
<input type=radio name='za' value='1'>Да
<input type=radio name='protiv' value='1'>Нет
Соответственно запись данных:
INSERT INTO table2 (id,za,protiv) VALUES (".$_POST['id'].",".$_POST['za'].",".$_POST['protiv']) | |
|
|
|
|
|
|
|
для: kosta_in_net
(28.01.2011 в 05:01)
| | Мнение непрофессионала.
Лично мне не понятно как Вы умудрились связать таблицы по автоинкрементным полям.
Вопрос такой: не лучше ли разделить "за" и "против" на разные поля
Что-то мне подсказывает, что не лучше.
Ввести 100 000 записей и протестить результат я, конечно, могу. Но не хочется тратить на это целый день.
А вот это совсем плохо. Потратив один день Вы получите ни с чем не сравнимый опыт, который останется с Вами навсегда, в противном случае Вы сами никогда не станете профессионалом.
___
Вы читали о нормализации таблиц? Мне кажется изучив нормализацию Вас никогда больше не будут волновать проблемы подобного рода. | |
|
|
|
|
|
|
|
для: Valick
(28.01.2011 в 07:48)
| | Извиняюсь за ошибку. Структура такова:
table1
id int(11) unsigned NOT NULL auto_increment
name varchar(20) NOT NULL
table2
id int(11) unsigned NOT NULL
golos tinyint(1) NOT NULL
То есть, без автоинкремента во второй таблице.
И так, какие тут проблемы с нормализацией? | |
|
|
|
|
|
|
|
для: kosta_in_net
(28.01.2011 в 08:31)
| | 1. А хоть какой нибудь уникальный индекс во второй таблице есть? Или даже вообще хоть какой нибудь индекс?
2. Как определить, кому принадлежит голос?
возможно вопросы несовсем в тему. Тогда по заданному вопросу: идея с полями za protiv мне не нравится. | |
|
|
|
|
|
|
|
для: Trianon
(28.01.2011 в 09:08)
| | уникальный индекс строится на двух полях: id предложения и id юзера (данное поле исключено из примера, так как не имеет значения для подсчета голосов - оно не влияет на количество). Это и ответ о том, как определить, кому принадлежит голос. Хотя фиксация авторства голоса сделана на всякий случай. Фактически, нужно знать лишь предложение и общее количество голосов. Можно было бы иметь все это в одной записи, сумируя в нее результаты голосования, и тогда получали бы 2 поля: za и protiv; id стало бы уникальным, да и вообще, все можно было бы сделать одной таблицей, а не двумя... Но, на всякий случай сохраняется авторство. Соответственно, много записей и 2 таблицы, вместо одной.
Именно в ситуации 2-х таблиц мне интересно мнение других о способах хранения. Хранение в 1-м поле требует громоздкий запрос для выборки. Это наводит на мысль о его ресурсозатратности и медленности. Хранение в 2-х полях требует чуть больше места, но, как мне кажется, должно давать выигрышь в скорости | |
|
|
|
|
|
|
|
для: kosta_in_net
(28.01.2011 в 09:34)
| |
SELECT p.name, SUM(state='pro') AS `pro`, SUM(state='contra') AS `contra`
FROM polls p
LEFT JOIN votes v ON v.poll_id = p.id
GROUP BY p.id , p.name
|
Легенда:
polls - table1
votes - table2
state - golos
1 - za - pro
2 - protiv - contra | |
|
|
|
|
|
|
|
для: Trianon
(28.01.2011 в 11:54)
| | а я и не знал, что можно сделать так: SUM(state='pro') век живи, век учись, и все равно - дураком помрешь :)
Ща посмотрим на это в деле | |
|
|
|
|
|
|
|
для: kosta_in_net
(28.01.2011 в 17:59)
| | Работает :) | |
|
|
|