2013-04-09 5 views
7

Мне нужно создать представление, которое имеет столбец с именем row_num, где будет вставлен номер строки, точно так же, как автоматическое приращение в обычной таблице.Создать представление с помощью столбца num_rows - MySQL

Я действительно новый с видами, поэтому, пожалуйста, со мной. Скажем Я эту нормальную таблицу:

| country | name | age | price | 
-------------------------------- 
| US  | john | 22 | 20 | 
| France | Anne | 10 | 15 | 
| Sweden | Alex | 49 | 10 | 

И так далее ...

мнение, я хочу создать это:

| country | name | price | row_num | 
    ------------------------------------ 
    | US  | john | 20 | 1 | 
    | France | Anne | 10 | 2 | 
    | Sweden | Alex | 5 | 3 | 

И так далее ...

Я могу сгенерировать row_num с одним выбором:

SELECT @i:[email protected]+1 AS row_num, testing.country, testing.name, testing.price 
FROM testing testing,(SELECT @i:=0) derivedTable 
order by name 

Но моя проблема заключается в объединении запроса выше с запросом, создающим представление. Это комбинированный запрос я пытаюсь:

CREATE OR REPLACE view vwx (country, name, price, num_row) AS SELECT mytable.country, mytable.name, mytable.price, @i:[email protected]+1 AS row_number 
    FROM testing testing,(SELECT @i:=0) derivedTable 
    order by name; 

Я получаю следующую ошибку: # 1351 - ВЫБРАТЬ View содержит переменную или параметр

Я знаю, что я не могу использовать отборное внутри отборное с представлениями, но я не вижу другого способа сделать это так, как хочу, но я уверен, что есть способ сделать это, но я просто не знаю, как это сделать. Вероятно, с функциями или процедурами, но я для них действительно новичок, поэтому мне неудобно создавать функции или процедуры в mysql.

Надеюсь, я ясно дал понять, что я более чем счастлив объяснить себя более подробно.

+1

Почему нет автоматического приращения, например, «обычной таблицы», которую вы можете использовать? – Neal

+0

Потому что я не проектировал эту таблицу, и эта таблица хранит тысячи и тысячи записей. Кроме того, они не позволяют мне что-либо менять на этом столе, поэтому я использую представления. – dazito

+0

Ах, и еще одна деталь @Neal, о которой я забыл упомянуть, это представление создается с предложением where, я не помещал его туда, поскольку я думал, что это не важная деталь. – dazito

ответ

5

Я нашел решение для этого:

Сначала нужно создать функцию:

delimiter // 

CREATE FUNCTION `func_inc_var_session`() RETURNS int 
    NO SQL 
    NOT DETERMINISTIC 
    begin 
     SET @var := @var + 1; 
     return @var; 
    end 
    // 

delimiter ; 

Затем установите @var на номер, который вы хотите, чтобы начать с. В этом случае нуль.

SET @var=0;

Затем создайте вид следующим образом:

CREATE OR REPLACE VIEW myview (place, name, hour, price, counter) 
AS SELECT place, name, hour, price, func_inc_var_session() 
FROM yourtable 
WHERE input_conditions_here; 

Хитрость здесь в том, что вы можете видеть NULL в столбце счетчика. Если это произойдет, снова установите @var на свой номер, а затем снова выполните SELECT *, и вы увидите, что столбец счетчика правильно заполнен.

+0

Когда я это делаю, с «order by» внутри «input_conditions_here», я получаю func_inc_var_session() в неправильном порядке. Я думаю, что здесь нужен подзапрос. – user43326

-1
CREATE OR REPLACE view vwx (country, name, price, num_row) AS 
SELECT country, name, price, @index := @index + 1 AS num_row 
FROM testing, (SELECT @index := 0) temp 
+4

Это невозможно Я боюсь, потому что он использует переменную в представлении create, я получаю ту же ошибку, что и раньше: 'Код ошибки: 1351. View SELECT содержит переменную или параметр \t 0.000 sec' – dazito

0

Попробуйте применить этот запрос к представлению -

CREATE TABLE testing (
    id int(11) NOT NULL DEFAULT 0, 
    country varchar(255) DEFAULT NULL, 
    name varchar(255) DEFAULT NULL, 
    age int(11) DEFAULT NULL, 
    price int(11) DEFAULT NULL, 
    PRIMARY KEY (id) 
); 

INSERT INTO testing(id, country, name, age, price) VALUES 
    (1, 'US', 'john', 22, 20), 
    (2, 'France', 'Anne', 10, 15), 
    (3, 'Sweden', 'Alex', 49, 10), 
    (4, 'France', 'Anne', 11, 16); 

SELECT 
    t1.*, COUNT(*) row_num 
FROM testing t1 
    LEFT JOIN testing t2 
    ON t2.name < t1.name OR (t2.name = t1.name AND t2.id <= t1.id) 
GROUP BY t1.name, t1.id; 

+----+---------+------+------+-------+---------+ 
| id | country | name | age | price | row_num | 
+----+---------+------+------+-------+---------+ 
| 3 | Sweden | Alex | 49 | 10 |  1 | 
| 2 | France | Anne | 10 | 15 |  2 | 
| 4 | France | Anne | 11 | 16 |  3 | 
| 1 | US  | john | 22 | 20 |  4 | 
+----+---------+------+------+-------+---------+ 
  • Этот запрос не использует пользовательские переменные, так что wotks в представлениях.
  • Дополнительное условие в предложении ON помогает реализовать дублированные значения в поле name.
+0

На вашей 5-й строке, где у вас есть 'ON t2.name dazito

+0

О, извините. Я имел в виду уникальный столбец идентификатора. Я добавлю полный пример. – Devart

1

Или попробуйте this-> создать временную таблицу и вставить данные в него, как сильфоне

CREATE OR REPLACE TEMPORARY TABLE myview (
    country VARCHAR(250), 
    name VARCHA(50), 
    price VARCHAR(50), 
    row_num int(11) 
); 

SET @row_num = 0; 
INSERT INTO myview (country,name,price,row_num) 
    SELECT @row_num:[email protected]_num+1 
     as country,name,price,row_num 
    FROM testing; 

SELECT * FROM myview; 

+---------+------+------+-------+---------+ 
| country | name | age | price | row_num | 
+---------+------+------+-------+---------+ 
| Sweden | Alex | 49 | 10 |  1 | 
| France | Anne | 10 | 15 |  2 | 
| France | Anne | 11 | 16 |  3 | 
| US  | john | 22 | 20 |  4 | 
+---------+------+------+-------+---------+ 
2

Я попытался примером функции func_inc_var_session.

Была небольшая проблема инициализации переменной сеанса, которую я решил использовать с помощью функции mysql IFNULL.

Под усиленной функцией func_inc_var_session.

CREATE DEFINER=`root`@`localhost` FUNCTION `func_inc_var_session`() RETURNS int(11) 
begin 
    SET @var := IFNULL(@var,0) + 1; 
    return @var; 
end 
+1

Обратите внимание на предостережение: если вы используете функцию дважды или более раз в одном запросе (например, с помощью JOIN), она будет продолжать увеличивать переменную. –

0

добавляя номер строки в результате запроса - Нет View нужно - один запрос

SELECT country, name, price, @ID := @ID + 1 AS row_num 
FROM testing, 
    (SELECT @ID := 0) temp 

Добавьте следующие строки в MySQL ConnectionString: Allow User Variables=True;

Не добавлять "Cross Присоединитесь "в вашем запросе, чтобы обновить вашу переменную @ID.

+0

Добро пожаловать в SO. Правильно составлен код форматирования в ваших ответах :-) – Blackbam

+0

OP хочет получить результат как представление, и ваш ответ не будет работать как просмотр. – user43326

1

При использовании решения от @dazito у вас может возникнуть проблема с постоянным увеличением счетчика от запроса к запросу, например, когда ваше приложение повторно использует сеанс, например, с JPA/Hibernate. Например:

Запрос 1:

 
| country | name | price | row_num | 
------------------------------------ 
| US  | john | 20 | 1 | 
| France | Anne | 10 | 2 | 
| Sweden | Alex | 5 | 3 | 

Запрос 2:

 
| country | name | price | row_num | 
------------------------------------ 
| US  | john | 20 | 4 | 
| France | Anne | 10 | 5 | 
| Sweden | Alex | 5 | 6 | 

т.д.

Одним из решений этой проблемы является присоединиться к основной запрос с (одноразовый) вызов функции счетчика и параметризация функции (параметр «сброс» ниже), чтобы сообщить, что это первый вызов.

 
delimiter // 
CREATE FUNCTION `func_inc_var_session`(reset BIT) RETURNS int 
    NO SQL 
    NOT DETERMINISTIC 
    begin 
     IF reset THEN 
     SET @var := 0; 
     ELSE 
     SET @var := IFNULL(@var,0) + 1; 
     END IF; 
     return @var; 
    end 
    // 
delimiter ; 

Теперь вы можете вызвать функцию в представлении запроса с параметром сброса установлен в 1, чтобы установить переменный счетчик функции обратно в 0, и 0, чтобы увеличить счетчик. Функция будет получить только вызывается один раз с 1 в качестве параметра при соединении с ним, как показано ниже:

 
CREATE OR REPLACE VIEW country_view (country, name, price, row_num) 
AS SELECT country, name, price, func_inc_var_session(0) 
FROM country 
JOIN (SELECT func_inc_var_session(1)) r 

Теперь вы гарантированный номер строки 1, 2, 3 каждый раз.

Смежные вопросы