从复杂查询中定义 mysql 中的视图 - 尝试 #2

Posted

技术标签:

【中文标题】从复杂查询中定义 mysql 中的视图 - 尝试 #2【英文标题】:Defining views in mysql from complex queries - Try #2 【发布时间】:2009-12-31 16:30:19 【问题描述】:

希望这种格式更好...感谢 OMG 小马、Peter Lang 和 asstander 耐心回答我的第一次尝试。

我正在设置一个游戏,其中每个用户每周选择一个 CONTESTANT,有点像选择你认为会赢的足球队。我需要创建一个视图,对于 USER、CONTESTANT 和 WEEK 的每个组合,该用户在该周累计选择了该特定 CONTESTANT 的次数。数据表如下所示:

Data table "contestants"
contestant  name
11          Aaron
12             Bob
13          Catherine
14          David

Data table "picks"
user    week    contestant
1001    1       11
1001    2       11
1002    1       12
1002    2       13

现在,我的代码可以正常工作并提供我想要的确切输出,但问题是,我无法从中查看,因为存在子查询。这是代码和正确的输出:

SELECT user, contestant ,week, count(valid_pick) num_picks 
  FROM
  (
  SELECT DISTINCT p.user , c.contestant, p.week  
    FROM contestants c , picks p
    ORDER BY user , contestant , week
  ) t1
  LEFT JOIN
  (
  SELECT user p_user , contestant p_contestant , week p_week ,
         1 as valid_pick  
    FROM picks p
    ORDER BY p.user , p_contestant , p_week
  ) t2
  ON t1.user = t2.p_user AND t1.contestant = t2.p_contestant 
     AND t2.p_week <= t1.week
GROUP BY user , contestant , week

user    contestant  week    num_picks
1001    11  1   1
1001    11  2   2
1001    12  1   0
1001    12  2   0
1001    13  1   0
1001    13  2   0
1001    14  1   0
1001    14  2   0
1002    11  1   0
1002    11  2   0
1002    12  1   1
1002    12  2   1
1002    13  1   0
1002    13  2   1
1002    14  1   0
1002    14  2   0

这在正确的位置有 0,并且正确地按周累计计算选秀权。

但我真的需要这个作为视图,所以我想将子查询创建为迷你视图。代码如下:

CREATE OR REPLACE VIEW miniview1 AS
  SELECT DISTINCT p.user , c.contestant, p.week  
    FROM contestants c , picks p
    ORDER BY user , contestant , week
;
CREATE OR REPLACE VIEW miniview2 AS
  SELECT user p_user , contestant p_contestant , week p_week ,
         1 as valid_pick  
    FROM picks p
    ORDER BY p.user , p_contestant , p_week
 ;
CREATE OR REPLACE VIEW myview AS
SELECT user, contestant ,week, count(valid_pick) num_picks 
  FROM miniview1 t1
  LEFT JOIN miniview2 t2
  ON t1.user = t2.p_user AND t1.contestant = t2.p_contestant 
     AND t2.p_week <= t1.week
GROUP BY user , contestant , week

但我得到的“myview”是这样的:

user    contestant  week    num_picks
1001    14  1   1
1002    14  1   1
1001    14  2   1
1002    14  2   1
1002    11  1   1
1002    11  2   1
1001    12  1   1
1001    12  2   1
1001    13  1   1
1002    13  1   1
1001    13  2   1
1001    11  1   1
1001    11  2   2
1002    12  1   1
1002    12  2   1
1002    13  2   1

显然这是错误的。这似乎是一个如此简单的替代。我检查了 miniview1 和 miniview2,它们完全正确。有什么想法吗?

感谢您对 mysql(和 ***)新手的耐心等待!

狗哥

【问题讨论】:

【参考方案1】:

我想你想要这样的东西:

Data table "contestants"
contestant  name
11          Aaron
12             Bob
13          Catherine
14          David

Data table "weeks"
contestant week
11         1
11         2
12         1
12         2

Data table "user"
user     name
1001     Fred
1002     Jane

Data table "picks"
user    week    contestant
1001    1       11
1001    2       11
1002    1       12
1002    2       13

select p.user, w.contestant, w.week,
    (select count(*)
        from picks p
        where p.week = w.week
        and p.contestant = w.contestant)
from user u
join weeks w 
join contestants c on c.contestant = w.contestant

请注意,此代码未经测试。

为了清楚起见,我留下了简短的名称,并且数据库被破坏了。可以稍微整理一下实现。

【讨论】:

感谢您的回答。我的问题(作为一个完整的 mysql 新手)真的是想了解 mysql 的操作。为什么当我将子查询写成视图然后插入视图时会得到不同的结果?感谢您的回答。【参考方案2】:

迷你视图1:

创建或替换视图 miniview1 AS 选择 p.user , c.contestant, p.week FROM 参赛者 c , 挑选 p GROUP BY 用户、参赛者、周;

迷你视图2:

SELECT 用户 p_user , 参赛者 p_contestant , 周 p_week , 1 作为有效选择 FROM 选择 p;

现在让我们尝试使用 miniview1 和 miniview2 的 SELECT

SELECT user, contestant ,week, count(valid_pick) num_picks 
  FROM 
   (  SELECT * from miniview1 ) t1
  LEFT JOIN
   (  SELECT * from miniview2 ) t2
ON t1.user = t2.p_user AND t1.contestant = t2.p_contestant 
AND t2.p_week <= t1.week
GROUP BY user , contestant , week;

这给出了与您的示例相同的正确结果。所以这似乎是 myview 的问题,而不是 miniview1 或 miniview2。

我认为这是因为您不能将上面的 SELECT 写为 VIEW。 SELECT 使用子查询,而 VIEW 不能使用子查询。

换句话说:上面的 SELECT 语句与 VIEW myview 的语义完全不同。

【讨论】:

谢谢。这是我试图理解的迷你视图的难题。【参考方案3】:

doxguy,你写道:

...我检查了 miniview1 和 miniview2,它们完全正确...

您期望 miniview1 的正确结果是什么?

当我尝试你对 miniview1 的定义时,我得到的结果对我来说显然是错误的:

从 miniview1 中选择 * 用户参赛周 1001 11 1 ... 1002 13 1 1002 13 2 1002 14 1 1002 14 2

但是 - 例如 - 根本没有与参赛者 #14 的比赛。

编辑:我知道这并不能回答您的问题。这只是我觉得奇怪的东西。

【讨论】:

我得到了你得到的,这与我运行子查询而不是将其写入 miniview1 时得到的结果相同。没有人选择 14 号选手,这是真的,但我希望 14 号选手在每个比赛周的决赛桌中都有一个 0,这就是我设置它的方式。也许有更好的方法来做到这一点(实际上我现在实际上以另一种方式完成了任务),但是正如您所指出的,我只是想了解为什么将此子查询写入视图然后使用视图给出不同的答案而不仅仅是直接使用子查询。感谢您花时间回答。

以上是关于从复杂查询中定义 mysql 中的视图 - 尝试 #2的主要内容,如果未能解决你的问题,请参考以下文章

mysql 视图

mysql数据库视图

从 mysql 中的查询创建视图 - mysql 不允许创建视图

MySQL:如何跟踪视图中的更改

MySQL之视图

11.Mysql视图