Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/73.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/wordpress/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 如何使用视图执行复杂的sql查询,而不是依赖中间(具体)表_Mysql_Sql_Select_View_Inner Join - Fatal编程技术网

Mysql 如何使用视图执行复杂的sql查询,而不是依赖中间(具体)表

Mysql 如何使用视图执行复杂的sql查询,而不是依赖中间(具体)表,mysql,sql,select,view,inner-join,Mysql,Sql,Select,View,Inner Join,SQL粉丝: 我正在尝试通过使用以下用例来挖掘我的一些生疏的sql技能: 假设我们有一家有线电视公司,有跟踪以下内容的db表: 电视节目, 观看我们节目的客户,以及 观看活动(特定客户观看特定节目的日期) 比如说,我们想要一份关于每个节目的浏览量和观众平均年龄的报告 观众。我在这里意识到的关键是,如果同一个人在不同的日期看X台节目两次 我们不能让这个人的年龄对“X秀观众的平均年龄”的计算贡献两倍 首先,我定义了我的表并在其中粘贴了一些数据(这是mysql语法,b.t.w): 现在,我创建了一

SQL粉丝:

我正在尝试通过使用以下用例来挖掘我的一些生疏的sql技能:

假设我们有一家有线电视公司,有跟踪以下内容的db表:

  • 电视节目,
  • 观看我们节目的客户,以及
  • 观看活动(特定客户观看特定节目的日期)
比如说,我们想要一份关于每个节目的浏览量和观众平均年龄的报告 观众。我在这里意识到的关键是,如果同一个人在不同的日期看X台节目两次 我们不能让这个人的年龄对“X秀观众的平均年龄”的计算贡献两倍

首先,我定义了我的表并在其中粘贴了一些数据(这是mysql语法,b.t.w):

现在,我创建了一个查询,将表连接起来,并给出每个客户的showname和年龄 谁看了一个节目

     select date, shows.showid, cust.custid, showname, age  from 
        ->                       watched 
        ->                           inner join
        ->                       cust
        ->                           on cust.custid = watched.custid
        ->                               inner join 
        ->                                   shows
        ->                               on shows.showid = watched.showid    ;
    +------+--------+--------+----------+-----+
    | date | showid | custid | showname | age |
    +------+--------+--------+----------+-----+
    |    1 |      1 |      1 | bingo    |  20 |
    |    2 |      1 |      1 | bingo    |  20 |
    |    3 |      1 |      1 | bingo    |  20 |
    |    4 |      1 |      1 | bingo    |  20 |
    |    1 |      1 |      2 | bingo    |  30 |
    |    1 |      1 |      3 | bingo    |  40 |
    |    1 |      1 |      4 | bingo    |  20 |
    |    2 |      2 |      2 | animals  |  30 |
    +------+--------+--------+----------+-----+
    8 rows in set (0.00 sec)
但请注意,customer id 1作为观察者多次出现 “宾果游戏”的表演,我希望他只算一次

因此,我创建了一个查询,列出了节目和观看过节目的客户, 但每个客户只统计一次

    mysql>  select age, showname, showid, custid  from 
        ->              ( select date, shows.showid, cust.custid, showname, age  from 
        ->                  watched 
        ->                      inner join
        ->                  cust
        ->                      on cust.custid = watched.custid
        ->                          inner join 
        ->                              shows
        ->                          on shows.showid = watched.showid    
        ->              ) as VIEWS
        ->          group by custid, showname;
    +-----+----------+--------+--------+
    | age | showname | showid | custid |
    +-----+----------+--------+--------+
    |  20 | bingo    |      1 |      1 |
    |  30 | animals  |      2 |      2 |
    |  30 | bingo    |      1 |      2 |
    |  40 | bingo    |      1 |      3 |
    |  20 | bingo    |      1 |      4 |
    +-----+----------+--------+--------+
    5 rows in set (0.00 sec)
接下来——还有(我希望你能给我一点建议)。。。 我试着创建一个视图,给我看的每一个节目的名字,看这个节目的人的平均年龄,以及节目id。 我计划加入一个查询,让我知道每个节目的浏览量。但视图创建失败,如图所示:

    mysql> create view viewages as 
        -> select showname, avg(age), showid
        ->       from 
        ->          (select age, showname, showid, custid  from 
        ->              ( select date, shows.showid, cust.custid, showname, age  from 
        ->                  watched 
        ->                      inner join
        ->                  cust
        ->                      on cust.custid = watched.custid
        ->                          inner join 
        ->                              shows
        ->                          on shows.showid = watched.showid    
        ->              ) as VIEWS
        ->          group by custid, showname)
        ->              as DISTINCT_CUST_VIEWS
        ->          group by showname;
    ERROR 1349 (HY000): View's SELECT contains a subquery in the FROM clause
好的。。所以那没用。我让它工作了,但我做的方式看起来很俗气。我使用中间表

有没有一位sql摇滚明星可以在没有桌子的情况下给我展示一种更好的方法。。也许有一个视角,就像我试过的那样 创造,或者更好的东西

以下是我的蹩脚解决方案:

drop table if exists viewage ;

create table viewage (
    showname varchar(256) not null,
    avg_age   float  not null,
    showid    int    not null
);

insert into viewage 
select showname, avg(age), showid
      from 
         (select age, showname, showid, custid  from 
             ( select date, shows.showid, cust.custid, showname, age  from 
                 watched 
                     inner join
                 cust
                     on cust.custid = watched.custid
                         inner join 
                             shows
                         on shows.showid = watched.showid    
             ) as VIEWS
         group by custid, showname)
             as DISTINCT_CUST_VIEWS
         group by showname;


##  Finally join the table with average age for each show with a query that does the count of views for each show:



drop table if exists viewage ;

create table viewage (
    showname varchar(256) not null,
    avg_age   float  not null,
    showid    int    not null
);

insert into viewage 
select showname, avg(age), showid
      from 
         (select age, showname, showid, custid  from 
             ( select date, shows.showid, cust.custid, showname, age  from 
                 watched 
                     inner join
                 cust
                     on cust.custid = watched.custid
                         inner join 
                             shows
                         on shows.showid = watched.showid    
             ) as VIEWS
         group by custid, showname)
             as DISTINCT_CUST_VIEWS
         group by showname;



select count(*), showname, avg_age from  
  watched 
    inner join 
  viewage
    on viewage.showid = watched.showid 
    group by showname;




+----------+----------+---------+
| count(*) | showname | avg_age |
+----------+----------+---------+
|        1 | animals  |      30 |
|        7 | bingo    |    27.5 |
+----------+----------+---------+
2 rows in set (0.00 sec)
提前感谢您的帮助

-克里斯

我试着创建一个视图,给我每个被观看的节目的名称, 观看该节目者的平均年龄,以及该节目的id

错误消息很清楚--

这里有一种解决这个特殊问题的方法

-- Age of each show's customers.
create or replace view show_cust_ages as 
select distinct watched.showid, cust.custid, cust.age
from watched 
inner join cust  on cust.custid = watched.custid;

-- Average age of show's customers. This queries the previous view.
create or replace view show_avg_ages as
select showid, avg(age) avg_age
from show_cust_ages
group by showid;

-- Your goal.
create or replace view show_name_avg_ages as
select t1.showid, t2.showname, t1.avg_age
from show_avg_ages t1
inner join shows t2 on t2.showid = t1.showid;
在制作过程中,我会花更多的时间思考事物的名称,而不是在这里


您应该知道,在MySQL中,基于视图的视图在大表上的性能可能很差。

感谢CREATE TABLE和INSERT语句。
-- Age of each show's customers.
create or replace view show_cust_ages as 
select distinct watched.showid, cust.custid, cust.age
from watched 
inner join cust  on cust.custid = watched.custid;

-- Average age of show's customers. This queries the previous view.
create or replace view show_avg_ages as
select showid, avg(age) avg_age
from show_cust_ages
group by showid;

-- Your goal.
create or replace view show_name_avg_ages as
select t1.showid, t2.showname, t1.avg_age
from show_avg_ages t1
inner join shows t2 on t2.showid = t1.showid;