使用列num_rows创建一个视图 - MySQL

时间:2013-04-09 01:52:05

标签: mysql views

我需要创建一个视图,其中有一个名为row_num的列,它将插入行号,就像普通表中的自动增量一样。

假设我有这个普通表:

| 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:=@i+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:=@i+1 AS row_number
    FROM testing testing,(SELECT @i:=0) derivedTable
    order by name;

我收到以下错误:#1351 - View的SELECT包含变量或参数

我知道我不能在带有视图的选择中使用选择,但我没有看到以我想要的方式进行此视图的其他方式,但我确信有办法做到这一点但我只是不喜欢不知道怎么做。可能有函数或程序,但我真的很新,所以我不习惯在mysql中创建函数或过程。

我希望自己明确表示,否则我非常乐意更详细地解释自己。

7 个答案:

答案 0 :(得分: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 *,您将看到正确填充的计数器列。

答案 1 :(得分: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

答案 2 :(得分:1)

或试试这个 - >创建一个临时表并将数据插入其中,如下所示

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:=@row_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 |
+---------+------+------+-------+---------+

答案 3 :(得分: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    |

对此的一个解决方案是将主查询与(一次)调用计数器函数并参数化函数(下面的' reset'参数)连接,让它知道它是第一个调用

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 ;

现在,您可以在视图查询中调用函数,并将reset参数设置为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行。

答案 4 :(得分: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 |
+----+---------+------+------+-------+---------+
  • 此查询不使用任何用户变量,因此它会在视图中显示。
  • ON子句中的附加条件有助于在name字段中实现重复值。

答案 5 :(得分:0)

在查询结果中添加行号 - 无需查看 - 一次查询

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

将以下内容添加到MySQL connectionString:Allow User Variables=True;

请勿在查询中添加“交叉加入”来更新@ID变量。

答案 6 :(得分:-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