我需要创建一个视图,其中有一个名为 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 - 视图的 SELECT 包含变量或参数
我知道我不能在带有视图的选择中使用选择,但我没有看到其他方法可以按照我想要的方式执行此视图,但我确信有一种方法可以做到这一点,但我只是不这样做知识。可能是函数或过程,但我对它们真的很陌生,所以我不习惯在 mysql 中创建函数或过程。
我希望我已经说清楚了,否则我非常乐意进一步详细地解释自己。
我找到了解决方案:
首先创建一个函数:
delimiter //
CREATE FUNCTION `func_inc_var_session`() RETURNS int
NO SQL
NOT DETERMINISTIC
begin
SET @var := @var + 1;
return @var;
end
//
delimiter ;
然后将@var 设置为您想要开始的数字。 在这种情况下为零。
设置@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 *,您将看到计数器列已正确填充。
我尝试了
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
使用 @dazito 的解决方案时,您可能会遇到计数器从查询到查询不断递增的问题,例如,当您的应用程序重用会话时,例如 JPA / Hibernate。例如:
查询1:
|国家 |名称 |价格|行号 | ------------------------------------------------ |美国 |约翰 | 20 | 20 1 | |法国 |安妮 | 10 | 10 2 | |瑞典 |亚历克斯 | 5 | 3 |
查询2:
|国家 |名称 |价格|行号 | ------------------------------------------------ |美国 |约翰 | 20 | 20 4 | |法国 |安妮 | 10 | 10 5 | |瑞典 |亚历克斯 | 5 | 6 |
等等
对此的一个解决方案是将主查询与对计数器函数的(一次性)调用结合起来,并对函数进行参数化(下面的“重置”参数)以让它知道这是第一次调用。
分隔符 // 创建函数 `func_inc_var_session`(重置位)返回 int 没有SQL 不确定性 开始 如果重置则 设置@var:= 0; 别的 设置 @var := IFNULL(@var,0) + 1; 万一; 返回@var; 结尾 // 分隔符;
现在您可以在视图查询中调用该函数,并将重置参数设置为 1,以将函数的计数器变量设置回 0,并使用 0 来递增计数器。当与它连接时,该函数只会被调用一次,并以 1 作为参数:
创建或替换视图country_view(国家/地区、名称、价格、row_num) AS SELECT 国家、名称、价格、func_inc_var_session(0) 来自国家 JOIN (SELECT func_inc_var_session(1)) r
现在您每次都保证行号为 1、2、3。
或者尝试这个->创建一个临时表并将数据插入其中,如下所示
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 |
+---------+------+------+-------+---------+
尝试将此查询应用于您的视图 -
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 |
+----+---------+------+------+-------+---------+
name
字段中实现重复值。MySql 从 8.0 版本开始支持
ROW_NUMBER()
功能,它允许您创建视图。旧方法(模拟所需行为)的问题在于,在创建视图时,@
中的(@row_number:=@row_number + 1)
混淆了视图创建的语法并抛出 #1351 错误。
CREATE OR REPLACE view vwx (country, name, price, num_row) AS
SELECT
country,
name,
price,
ROW_NUMBER() OVER (ORDER BY final_score) row_num
FROM
testing
ORDER BY
name
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
向查询结果添加行号 - 无需查看 - 一次查询
SELECT country, name, price, @ID := @ID + 1 AS row_num
FROM testing,
(SELECT @ID := 0) temp
将以下内容添加到您的 MySQL 连接字符串:
Allow User Variables=True;
请勿在查询中添加“Cross Join”来更新 @ID 变量。
警告:尝试在视图中使用它会导致:
View's SELECT contains a variable or parameter